nsCOMPtr.h
上传用户:goldcmy89
上传日期:2017-12-03
资源大小:2246k
文件大小:46k
源码类别:

PlugIns编程

开发平台:

Visual C++

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Scott Collins <scc@mozilla.org> (original author)
  24.  *   L. David Baron <dbaron@dbaron.org>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  28.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39. #ifndef nsCOMPtr_h___
  40. #define nsCOMPtr_h___
  41. /*
  42.   Having problems?
  43.   
  44.   See the User Manual at:
  45.     http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
  46.   nsCOMPtr
  47.     better than a raw pointer
  48.   for owning objects
  49.                        -- scc
  50. */
  51.   // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
  52. #ifndef nsDebug_h___
  53. #include "nsDebug.h"
  54.   // for |NS_PRECONDITION|
  55. #endif
  56. #ifndef nsISupportsUtils_h__
  57. #include "nsISupportsUtils.h"
  58.   // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
  59. #endif
  60. #ifndef nscore_h___
  61. #include "nscore.h"
  62.   // for |NS_..._CAST|, |NS_COM_GLUE|
  63. #endif
  64. /*
  65.   WARNING:
  66.     This file defines several macros for internal use only.  These macros begin with the
  67.     prefix |NSCAP_|.  Do not use these macros in your own code.  They are for internal use
  68.     only for cross-platform compatibility, and are subject to change without notice.
  69. */
  70. #ifdef _MSC_VER
  71.   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  72.     // under VC++, we win by inlining StartAssignment
  73.     // Also under VC++, at the highest warning level, we are overwhelmed  with warnings
  74.     //  about (unused) inline functions being removed.  This is to be expected with
  75.     //  templates, so we disable the warning.
  76.   #pragma warning( disable: 4514 )
  77. #endif
  78. #define NSCAP_FEATURE_USE_BASE
  79. #ifdef NS_DEBUG
  80.   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
  81.   #undef NSCAP_FEATURE_USE_BASE
  82. //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
  83. #endif
  84.   /*
  85.     |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is 
  86.     problematic on a select few of our platforms, e.g., QNX.  Therefore, I'm providing
  87.     a mechanism by which these features can be explicitly disabled from the command-line.
  88.   */
  89. #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
  90.   #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  91. #endif
  92. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
  93.   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
  94.   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
  95.   // don't reorder instructions based on aliasing assumptions for
  96.   // this variable.  Fortunately, gcc versions < 3.3 do not do any
  97.   // optimizations that break nsCOMPtr.
  98.   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
  99. #else
  100.   #define NS_MAY_ALIAS_PTR(t)    t*
  101. #endif
  102. #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
  103.   #define NSCAP_FEATURE_USE_BASE
  104. #endif
  105. #ifdef HAVE_CPP_BOOL
  106.   typedef bool NSCAP_BOOL;
  107. #else
  108.   typedef PRBool NSCAP_BOOL;
  109. #endif
  110.   /*
  111.     The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
  112.       allow external clients the ability to add logging or other interesting debug facilities.
  113.       In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
  114.       provide (e.g., in "nsTraceRefcnt.h") suitable definitions
  115.         #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
  116.         #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
  117.   */
  118. #ifndef NSCAP_ADDREF
  119.   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
  120. #endif
  121. #ifndef NSCAP_RELEASE
  122.   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
  123. #endif
  124.   // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
  125. #ifdef NSCAP_LOG_ASSIGNMENT
  126.     // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
  127.     //  to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
  128.     //  the |nsCOMPtr|.
  129.   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
  130. #else
  131.     // ...otherwise, just strip it out of the code
  132.   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
  133. #endif
  134. #ifndef NSCAP_LOG_RELEASE
  135.   #define NSCAP_LOG_RELEASE(this, ptr)
  136. #endif
  137.   /*
  138.     WARNING:
  139.       VC++4.2 is very picky.  To compile under VC++4.2, the classes must be defined
  140.       in an order that satisfies:
  141.     
  142.         nsDerivedSafe < nsCOMPtr
  143.         already_AddRefed < nsCOMPtr
  144.         nsCOMPtr < nsGetterAddRefs
  145.       The other compilers probably won't complain, so please don't reorder these
  146.       classes, on pain of breaking 4.2 compatibility.
  147.   */
  148. template <class T>
  149. class nsDerivedSafe : public T
  150.     /*
  151.       No client should ever see or have to type the name of this class.  It is the
  152.       artifact that makes it a compile-time error to call |AddRef| and |Release|
  153.       on a |nsCOMPtr|.  DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
  154.       See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
  155.       This type should be a nested class inside |nsCOMPtr<T>|.
  156.     */
  157.   {
  158.     private:
  159. #ifdef HAVE_CPP_ACCESS_CHANGING_USING
  160.       using T::AddRef;
  161.       using T::Release;
  162. #else
  163.       nsrefcnt AddRef(void);
  164.       nsrefcnt Release(void);
  165. #endif
  166. #if !defined(AIX) && !defined(IRIX)
  167.       void operator delete( void*, size_t );                  // NOT TO BE IMPLEMENTED
  168.         // declaring |operator delete| private makes calling delete on an interface pointer a compile error
  169. #endif
  170.       nsDerivedSafe<T>& operator=( const T& );                // NOT TO BE IMPLEMENTED
  171.         // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
  172.         /*
  173.           Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
  174.           If you see that, that means somebody checked in a [XP]COM interface class that declares an
  175.           |operator=()|, and that's _bad_.  So bad, in fact, that this declaration exists explicitly
  176.           to stop people from doing it.
  177.         */
  178.     protected:
  179.       nsDerivedSafe();                                        // NOT TO BE IMPLEMENTED
  180.         /*
  181.           This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
  182.           default ctor but inheriting classes without an empty ctor. See bug 209667.
  183.         */
  184.   };
  185. #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
  186. template <class T>
  187. nsrefcnt
  188. nsDerivedSafe<T>::AddRef()
  189.   {
  190.     return 0;
  191.   }
  192. template <class T>
  193. nsrefcnt
  194. nsDerivedSafe<T>::Release()
  195.   {
  196.     return 0;
  197.   }
  198. #endif
  199. template <class T>
  200. struct already_AddRefed
  201.     /*
  202.       ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
  203.       |AddRef|ing it.  You might want to use this as a return type from a function
  204.       that produces an already |AddRef|ed pointer as a result.
  205.       See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
  206.       This type should be a nested class inside |nsCOMPtr<T>|.
  207.       Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
  208.       avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
  209.       case, and perhaps worth the savings in time and space that its specific
  210.       implementation affords over the more general solution offered by
  211.       |nsCOMPtr_helper|.
  212.     */
  213.   {
  214.     already_AddRefed( T* aRawPtr )
  215.         : mRawPtr(aRawPtr)
  216.       {
  217.         // nothing else to do here
  218.       }
  219.     T* get() const { return mRawPtr; }
  220.     T* mRawPtr;
  221.   };
  222. template <class T>
  223. inline
  224. const already_AddRefed<T>
  225. getter_AddRefs( T* aRawPtr )
  226.     /*
  227.       ...makes typing easier, because it deduces the template type, e.g., 
  228.       you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
  229.     */
  230.   {
  231.     return already_AddRefed<T>(aRawPtr);
  232.   }
  233. template <class T>
  234. inline
  235. const already_AddRefed<T>
  236. getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
  237.   {
  238.     return aAlreadyAddRefedPtr;
  239.   }
  240. template <class T>
  241. inline
  242. const already_AddRefed<T>
  243. dont_AddRef( T* aRawPtr )
  244.   {
  245.     return already_AddRefed<T>(aRawPtr);
  246.   }
  247. template <class T>
  248. inline
  249. const already_AddRefed<T>
  250. dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
  251.   {
  252.     return aAlreadyAddRefedPtr;
  253.   }
  254. class nsCOMPtr_helper
  255.     /*
  256.       An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
  257.       that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
  258.       Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
  259.       Here are the rules for a helper:
  260.         - it implements |operator()| to produce an interface pointer
  261.         - (except for its name) |operator()| is a valid [XP]COM `getter'
  262.         - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
  263.         - it matches the type requested with the supplied |nsIID| argument
  264.         - its constructor provides an optional |nsresult*| that |operator()| can fill
  265.           in with an error when it is executed
  266.           
  267.       See |class nsGetInterface| for an example.
  268.     */
  269.   {
  270.     public:
  271.       virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
  272.   };
  273. /*
  274.   |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
  275.   avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
  276.   is called often enough that the codesize savings are big enough to
  277.   warrant the specialcasing.
  278. */
  279. class NS_COM_GLUE nsQueryInterface
  280.   {
  281.     public:
  282.       explicit
  283.       nsQueryInterface( nsISupports* aRawPtr )
  284.           : mRawPtr(aRawPtr)
  285.         {
  286.           // nothing else to do here
  287.         }
  288.       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  289.     private:
  290.       nsISupports*  mRawPtr;
  291.   };
  292. class NS_COM_GLUE nsQueryInterfaceWithError
  293.   {
  294.     public:
  295.       nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
  296.           : mRawPtr(aRawPtr),
  297.             mErrorPtr(error)
  298.         {
  299.           // nothing else to do here
  300.         }
  301.       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  302.     private:
  303.       nsISupports*  mRawPtr;
  304.       nsresult*     mErrorPtr;
  305.   };
  306. inline
  307. nsQueryInterface
  308. do_QueryInterface( nsISupports* aRawPtr )
  309.   {
  310.     return nsQueryInterface(aRawPtr);
  311.   }
  312. inline
  313. nsQueryInterfaceWithError
  314. do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
  315.   {
  316.     return nsQueryInterfaceWithError(aRawPtr, error);
  317.   }
  318. template <class T>
  319. inline
  320. void
  321. do_QueryInterface( already_AddRefed<T>& )
  322.   {
  323.     // This signature exists soley to _stop_ you from doing the bad thing.
  324.     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  325.     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  326.   }
  327. template <class T>
  328. inline
  329. void
  330. do_QueryInterface( already_AddRefed<T>&, nsresult* )
  331.   {
  332.     // This signature exists soley to _stop_ you from doing the bad thing.
  333.     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  334.     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  335.   }
  336. ////////////////////////////////////////////////////////////////////////////
  337. // Using servicemanager with COMPtrs
  338. class NS_COM_GLUE nsGetServiceByCID
  339. {
  340.  public:
  341.     nsGetServiceByCID(const nsCID& aCID)
  342.         : mCID(aCID)
  343.         {
  344.             // nothing else to do
  345.         }
  346.     
  347.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  348.     
  349.  private:
  350.     const nsCID&                mCID;
  351. };
  352. class NS_COM_GLUE nsGetServiceByCIDWithError
  353. {
  354.  public:
  355.     nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
  356.         : mCID(aCID),
  357.           mErrorPtr(aErrorPtr)
  358.         {
  359.             // nothing else to do
  360.         }
  361.     
  362.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  363.     
  364.  private:
  365.     const nsCID&                mCID;
  366.     nsresult*                   mErrorPtr;
  367. };
  368. class NS_COM_GLUE nsGetServiceByContractID
  369. {
  370.  public:
  371.     nsGetServiceByContractID(const char* aContractID)
  372.         : mContractID(aContractID)
  373.         {
  374.             // nothing else to do
  375.         }
  376.     
  377.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  378.     
  379.  private:
  380.     const char*                 mContractID;
  381. };
  382. class NS_COM_GLUE nsGetServiceByContractIDWithError
  383. {
  384.  public:
  385.     nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
  386.         : mContractID(aContractID),
  387.           mErrorPtr(aErrorPtr)
  388.         {
  389.             // nothing else to do
  390.         }
  391.     
  392.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  393.     
  394.  private:
  395.     const char*                 mContractID;
  396.     nsresult*                   mErrorPtr;
  397. };
  398. class nsCOMPtr_base
  399.     /*
  400.       ...factors implementation for all template versions of |nsCOMPtr|.
  401.       This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
  402.       because unlike the
  403.       Here's the way people normally do things like this
  404.       
  405.         template <class T> class Foo { ... };
  406.         template <> class Foo<void*> { ... };
  407.         template <class T> class Foo<T*> : private Foo<void*> { ... };
  408.     */
  409.   {
  410.     public:
  411.       nsCOMPtr_base( nsISupports* rawPtr = 0 )
  412.           : mRawPtr(rawPtr)
  413.         {
  414.           // nothing else to do here
  415.         }
  416.       NS_COM_GLUE NS_FASTCALL ~nsCOMPtr_base();
  417.       NS_COM_GLUE void NS_FASTCALL   assign_with_AddRef( nsISupports* );
  418.       NS_COM_GLUE void NS_FASTCALL   assign_from_qi( const nsQueryInterface, const nsIID& );
  419.       NS_COM_GLUE void NS_FASTCALL   assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  420.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  421.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  422.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  423.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  424.       NS_COM_GLUE void NS_FASTCALL   assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  425.       NS_COM_GLUE void** NS_FASTCALL begin_assignment();
  426.     protected:
  427.       NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
  428.       void
  429.       assign_assuming_AddRef( nsISupports* newPtr )
  430.         {
  431.             /*
  432.               |AddRef()|ing the new value (before entering this function) before
  433.               |Release()|ing the old lets us safely ignore the self-assignment case.
  434.               We must, however, be careful only to |Release()| _after_ doing the
  435.               assignment, in case the |Release()| leads to our _own_ destruction,
  436.               which would, in turn, cause an incorrect second |Release()| of our old
  437.               pointer.  Thank <waterson@netscape.com> for discovering this.
  438.             */
  439.           nsISupports* oldPtr = mRawPtr;
  440.           mRawPtr = newPtr;
  441.           NSCAP_LOG_ASSIGNMENT(this, newPtr);
  442.           NSCAP_LOG_RELEASE(this, oldPtr);
  443.           if ( oldPtr )
  444.             NSCAP_RELEASE(this, oldPtr);
  445.         }
  446.   };
  447. // template <class T> class nsGetterAddRefs;
  448. template <class T>
  449. class nsCOMPtr
  450. #ifdef NSCAP_FEATURE_USE_BASE
  451.     : private nsCOMPtr_base
  452. #endif
  453.   {
  454. #ifdef NSCAP_FEATURE_USE_BASE
  455.   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
  456. #else
  457.   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
  458.     private:
  459.       void    assign_with_AddRef( nsISupports* );
  460.       void    assign_from_qi( const nsQueryInterface, const nsIID& );
  461.       void    assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  462.       void    assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  463.       void    assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  464.       void    assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  465.       void    assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  466.       void    assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  467.       void**  begin_assignment();
  468.       void
  469.       assign_assuming_AddRef( T* newPtr )
  470.         {
  471.           T* oldPtr = mRawPtr;
  472.           mRawPtr = newPtr;
  473.           NSCAP_LOG_ASSIGNMENT(this, newPtr);
  474.           NSCAP_LOG_RELEASE(this, oldPtr);
  475.           if ( oldPtr )
  476.             NSCAP_RELEASE(this, oldPtr);
  477.         }
  478.     private:
  479.       T* mRawPtr;
  480. #endif
  481.     public:
  482.       typedef T element_type;
  483.       
  484. #ifndef NSCAP_FEATURE_USE_BASE
  485.      ~nsCOMPtr()
  486.         {
  487.           NSCAP_LOG_RELEASE(this, mRawPtr);
  488.           if ( mRawPtr )
  489.             NSCAP_RELEASE(this, mRawPtr);
  490.         }
  491. #endif
  492. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  493.       void
  494.       Assert_NoQueryNeeded()
  495.         {
  496.           if ( mRawPtr )
  497.             {
  498.               nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
  499.               NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
  500.             }
  501.         }
  502.   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
  503. #else
  504.   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
  505. #endif
  506.         // Constructors
  507.       nsCOMPtr()
  508.             : NSCAP_CTOR_BASE(0)
  509.           // default constructor
  510.         {
  511.           NSCAP_LOG_ASSIGNMENT(this, 0);
  512.         }
  513.       nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
  514.             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  515.           // copy-constructor
  516.         {
  517.           if ( mRawPtr )
  518.             NSCAP_ADDREF(this, mRawPtr);
  519.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  520.         }
  521.       nsCOMPtr( T* aRawPtr )
  522.             : NSCAP_CTOR_BASE(aRawPtr)
  523.           // construct from a raw pointer (of the right type)
  524.         {
  525.           if ( mRawPtr )
  526.             NSCAP_ADDREF(this, mRawPtr);
  527.           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  528.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  529.         }
  530.       nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
  531.             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  532.           // construct from |dont_AddRef(expr)|
  533.         {
  534.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  535.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  536.         }
  537.       nsCOMPtr( const nsQueryInterface qi )
  538.             : NSCAP_CTOR_BASE(0)
  539.           // construct from |do_QueryInterface(expr)|
  540.         {
  541.           NSCAP_LOG_ASSIGNMENT(this, 0);
  542.           assign_from_qi(qi, NS_GET_IID(T));
  543.         }
  544.       nsCOMPtr( const nsQueryInterfaceWithError& qi )
  545.             : NSCAP_CTOR_BASE(0)
  546.           // construct from |do_QueryInterface(expr, &rv)|
  547.         {
  548.           NSCAP_LOG_ASSIGNMENT(this, 0);
  549.           assign_from_qi_with_error(qi, NS_GET_IID(T));
  550.         }
  551.       nsCOMPtr( const nsGetServiceByCID gs )
  552.             : NSCAP_CTOR_BASE(0)
  553.           // construct from |do_GetService(cid_expr)|
  554.         {
  555.           NSCAP_LOG_ASSIGNMENT(this, 0);
  556.           assign_from_gs_cid(gs, NS_GET_IID(T));
  557.         }
  558.       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  559.             : NSCAP_CTOR_BASE(0)
  560.           // construct from |do_GetService(cid_expr, &rv)|
  561.         {
  562.           NSCAP_LOG_ASSIGNMENT(this, 0);
  563.           assign_from_gs_cid_with_error(gs, NS_GET_IID(T));
  564.         }
  565.       nsCOMPtr( const nsGetServiceByContractID gs )
  566.             : NSCAP_CTOR_BASE(0)
  567.           // construct from |do_GetService(contractid_expr)|
  568.         {
  569.           NSCAP_LOG_ASSIGNMENT(this, 0);
  570.           assign_from_gs_contractid(gs, NS_GET_IID(T));
  571.         }
  572.       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  573.             : NSCAP_CTOR_BASE(0)
  574.           // construct from |do_GetService(contractid_expr, &rv)|
  575.         {
  576.           NSCAP_LOG_ASSIGNMENT(this, 0);
  577.           assign_from_gs_contractid_with_error(gs, NS_GET_IID(T));
  578.         }
  579.       nsCOMPtr( const nsCOMPtr_helper& helper )
  580.             : NSCAP_CTOR_BASE(0)
  581.           // ...and finally, anything else we might need to construct from
  582.           //  can exploit the |nsCOMPtr_helper| facility
  583.         {
  584.           NSCAP_LOG_ASSIGNMENT(this, 0);
  585.           assign_from_helper(helper, NS_GET_IID(T));
  586.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  587.         }
  588.         // Assignment operators
  589.       nsCOMPtr<T>&
  590.       operator=( const nsCOMPtr<T>& rhs )
  591.           // copy assignment operator
  592.         {
  593.           assign_with_AddRef(rhs.mRawPtr);
  594.           return *this;
  595.         }
  596.       nsCOMPtr<T>&
  597.       operator=( T* rhs )
  598.           // assign from a raw pointer (of the right type)
  599.         {
  600.           assign_with_AddRef(rhs);
  601.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  602.           return *this;
  603.         }
  604.       nsCOMPtr<T>&
  605.       operator=( const already_AddRefed<T>& rhs )
  606.           // assign from |dont_AddRef(expr)|
  607.         {
  608.           assign_assuming_AddRef(rhs.mRawPtr);
  609.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  610.           return *this;
  611.         }
  612.       nsCOMPtr<T>&
  613.       operator=( const nsQueryInterface rhs )
  614.           // assign from |do_QueryInterface(expr)|
  615.         {
  616.           assign_from_qi(rhs, NS_GET_IID(T));
  617.           return *this;
  618.         }
  619.       nsCOMPtr<T>&
  620.       operator=( const nsQueryInterfaceWithError& rhs )
  621.           // assign from |do_QueryInterface(expr, &rv)|
  622.         {
  623.           assign_from_qi_with_error(rhs, NS_GET_IID(T));
  624.           return *this;
  625.         }
  626.       nsCOMPtr<T>&
  627.       operator=( const nsGetServiceByCID rhs )
  628.           // assign from |do_GetService(cid_expr)|
  629.         {
  630.           assign_from_gs_cid(rhs, NS_GET_IID(T));
  631.           return *this;
  632.         }
  633.       nsCOMPtr<T>&
  634.       operator=( const nsGetServiceByCIDWithError& rhs )
  635.           // assign from |do_GetService(cid_expr, &rv)|
  636.         {
  637.           assign_from_gs_cid_with_error(rhs, NS_GET_IID(T));
  638.           return *this;
  639.         }
  640.       nsCOMPtr<T>&
  641.       operator=( const nsGetServiceByContractID rhs )
  642.           // assign from |do_GetService(contractid_expr)|
  643.         {
  644.           assign_from_gs_contractid(rhs, NS_GET_IID(T));
  645.           return *this;
  646.         }
  647.       nsCOMPtr<T>&
  648.       operator=( const nsGetServiceByContractIDWithError& rhs )
  649.           // assign from |do_GetService(contractid_expr, &rv)|
  650.         {
  651.           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(T));
  652.           return *this;
  653.         }
  654.       nsCOMPtr<T>&
  655.       operator=( const nsCOMPtr_helper& rhs )
  656.           // ...and finally, anything else we might need to assign from
  657.           //  can exploit the |nsCOMPtr_helper| facility.
  658.         {
  659.           assign_from_helper(rhs, NS_GET_IID(T));
  660.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  661.           return *this;
  662.         }
  663.       void
  664.       swap( nsCOMPtr<T>& rhs )
  665.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  666.         {
  667. #ifdef NSCAP_FEATURE_USE_BASE
  668.           nsISupports* temp = rhs.mRawPtr;
  669. #else
  670.           T* temp = rhs.mRawPtr;
  671. #endif
  672.           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  673.           NSCAP_LOG_ASSIGNMENT(this, temp);
  674.           NSCAP_LOG_RELEASE(this, mRawPtr);
  675.           NSCAP_LOG_RELEASE(&rhs, temp);
  676.           rhs.mRawPtr = mRawPtr;
  677.           mRawPtr = temp;
  678.           // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
  679.         }
  680.       void
  681.       swap( T*& rhs )
  682.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  683.         {
  684. #ifdef NSCAP_FEATURE_USE_BASE
  685.           nsISupports* temp = rhs;
  686. #else
  687.           T* temp = rhs;
  688. #endif
  689.           NSCAP_LOG_ASSIGNMENT(this, temp);
  690.           NSCAP_LOG_RELEASE(this, mRawPtr);
  691.           rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
  692.           mRawPtr = temp;
  693.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  694.         }
  695.         // Other pointer operators
  696.       nsDerivedSafe<T>*
  697.       get() const
  698.           /*
  699.             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
  700.              Use |get()| _only_ to resolve ambiguity.
  701.             Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
  702.           */
  703.         {
  704.           return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
  705.         }
  706.       operator nsDerivedSafe<T>*() const
  707.           /*
  708.             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  709.               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
  710.               that makes an |nsCOMPtr| substitutable for a raw pointer.
  711.             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  712.           */
  713.         {
  714.           return get();
  715.         }
  716.       nsDerivedSafe<T>*
  717.       operator->() const
  718.         {
  719.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  720.           return get();
  721.         }
  722. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  723.   // broken version for IRIX
  724.       nsCOMPtr<T>*
  725.       get_address() const
  726.           // This is not intended to be used by clients.  See |address_of|
  727.           // below.
  728.         {
  729.           return NS_CONST_CAST(nsCOMPtr<T>*, this);
  730.         }
  731. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  732.       nsCOMPtr<T>*
  733.       get_address()
  734.           // This is not intended to be used by clients.  See |address_of|
  735.           // below.
  736.         {
  737.           return this;
  738.         }
  739.       const nsCOMPtr<T>*
  740.       get_address() const
  741.           // This is not intended to be used by clients.  See |address_of|
  742.           // below.
  743.         {
  744.           return this;
  745.         }
  746. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  747.     public:
  748.       nsDerivedSafe<T>&
  749.       operator*() const
  750.         {
  751.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  752.           return *get();
  753.         }
  754. #if 0
  755.     private:
  756.       friend class nsGetterAddRefs<T>;
  757. #endif
  758.       T**
  759.       StartAssignment()
  760.         {
  761. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  762.           return NS_REINTERPRET_CAST(T**, begin_assignment());
  763. #else
  764.           assign_assuming_AddRef(0);
  765.           return NS_REINTERPRET_CAST(T**, &mRawPtr);
  766. #endif
  767.         }
  768.   };
  769.   /*
  770.     Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
  771.     same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
  772.     to any valid [XP]COM interface.  Otherwise, an |nsCOMPtr<nsISupports>| would only be able
  773.     to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
  774.     querying ensues.  Clients need to be able to pass around arbitrary interface pointers,
  775.     without hassles, through intermediary code that doesn't know the exact type.
  776.   */
  777. NS_SPECIALIZE_TEMPLATE
  778. class nsCOMPtr<nsISupports>
  779.     : private nsCOMPtr_base
  780.   {
  781.     public:
  782.       typedef nsISupports element_type;
  783.         // Constructors
  784.       nsCOMPtr()
  785.             : nsCOMPtr_base(0)
  786.           // default constructor
  787.         {
  788.           NSCAP_LOG_ASSIGNMENT(this, 0);
  789.         }
  790.       nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
  791.             : nsCOMPtr_base(aSmartPtr.mRawPtr)
  792.           // copy constructor
  793.         {
  794.           if ( mRawPtr )
  795.             NSCAP_ADDREF(this, mRawPtr);
  796.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  797.         }
  798.       nsCOMPtr( nsISupports* aRawPtr )
  799.             : nsCOMPtr_base(aRawPtr)
  800.           // construct from a raw pointer (of the right type)
  801.         {
  802.           if ( mRawPtr )
  803.             NSCAP_ADDREF(this, mRawPtr);
  804.           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  805.         }
  806.       nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
  807.             : nsCOMPtr_base(aSmartPtr.mRawPtr)
  808.           // construct from |dont_AddRef(expr)|
  809.         {
  810.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  811.         }
  812.       nsCOMPtr( const nsQueryInterface qi )
  813.             : nsCOMPtr_base(0)
  814.           // assign from |do_QueryInterface(expr)|
  815.         {
  816.           NSCAP_LOG_ASSIGNMENT(this, 0);
  817.           assign_from_qi(qi, NS_GET_IID(nsISupports));
  818.         }
  819.       nsCOMPtr( const nsQueryInterfaceWithError& qi )
  820.             : nsCOMPtr_base(0)
  821.           // assign from |do_QueryInterface(expr, &rv)|
  822.         {
  823.           NSCAP_LOG_ASSIGNMENT(this, 0);
  824.           assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
  825.         }
  826.       nsCOMPtr( const nsGetServiceByCID gs )
  827.             : nsCOMPtr_base(0)
  828.           // assign from |do_GetService(cid_expr)|
  829.         {
  830.           NSCAP_LOG_ASSIGNMENT(this, 0);
  831.           assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
  832.         }
  833.       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  834.             : nsCOMPtr_base(0)
  835.           // assign from |do_GetService(cid_expr, &rv)|
  836.         {
  837.           NSCAP_LOG_ASSIGNMENT(this, 0);
  838.           assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
  839.         }
  840.       nsCOMPtr( const nsGetServiceByContractID gs )
  841.             : nsCOMPtr_base(0)
  842.           // assign from |do_GetService(contractid_expr)|
  843.         {
  844.           NSCAP_LOG_ASSIGNMENT(this, 0);
  845.           assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
  846.         }
  847.       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  848.             : nsCOMPtr_base(0)
  849.           // assign from |do_GetService(contractid_expr, &rv)|
  850.         {
  851.           NSCAP_LOG_ASSIGNMENT(this, 0);
  852.           assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
  853.         }
  854.       nsCOMPtr( const nsCOMPtr_helper& helper )
  855.             : nsCOMPtr_base(0)
  856.           // ...and finally, anything else we might need to construct from
  857.           //  can exploit the |nsCOMPtr_helper| facility
  858.         {
  859.           NSCAP_LOG_ASSIGNMENT(this, 0);
  860.           assign_from_helper(helper, NS_GET_IID(nsISupports));
  861.         }
  862.         // Assignment operators
  863.       nsCOMPtr<nsISupports>&
  864.       operator=( const nsCOMPtr<nsISupports>& rhs )
  865.           // copy assignment operator
  866.         {
  867.           assign_with_AddRef(rhs.mRawPtr);
  868.           return *this;
  869.         }
  870.       nsCOMPtr<nsISupports>&
  871.       operator=( nsISupports* rhs )
  872.           // assign from a raw pointer (of the right type)
  873.         {
  874.           assign_with_AddRef(rhs);
  875.           return *this;
  876.         }
  877.       nsCOMPtr<nsISupports>&
  878.       operator=( const already_AddRefed<nsISupports>& rhs )
  879.           // assign from |dont_AddRef(expr)|
  880.         {
  881.           assign_assuming_AddRef(rhs.mRawPtr);
  882.           return *this;
  883.         }
  884.       nsCOMPtr<nsISupports>&
  885.       operator=( const nsQueryInterface rhs )
  886.           // assign from |do_QueryInterface(expr)|
  887.         {
  888.           assign_from_qi(rhs, NS_GET_IID(nsISupports));
  889.           return *this;
  890.         }
  891.       nsCOMPtr<nsISupports>&
  892.       operator=( const nsQueryInterfaceWithError& rhs )
  893.           // assign from |do_QueryInterface(expr, &rv)|
  894.         {
  895.           assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
  896.           return *this;
  897.         }
  898.       nsCOMPtr<nsISupports>&
  899.       operator=( const nsGetServiceByCID rhs )
  900.           // assign from |do_GetService(cid_expr)|
  901.         {
  902.           assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
  903.           return *this;
  904.         }
  905.       nsCOMPtr<nsISupports>&
  906.       operator=( const nsGetServiceByCIDWithError& rhs )
  907.           // assign from |do_GetService(cid_expr, &rv)|
  908.         {
  909.           assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
  910.           return *this;
  911.         }
  912.       nsCOMPtr<nsISupports>&
  913.       operator=( const nsGetServiceByContractID rhs )
  914.           // assign from |do_GetService(contractid_expr)|
  915.         {
  916.           assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
  917.           return *this;
  918.         }
  919.       nsCOMPtr<nsISupports>&
  920.       operator=( const nsGetServiceByContractIDWithError& rhs )
  921.           // assign from |do_GetService(contractid_expr, &rv)|
  922.         {
  923.           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
  924.           return *this;
  925.         }
  926.       nsCOMPtr<nsISupports>&
  927.       operator=( const nsCOMPtr_helper& rhs )
  928.           // ...and finally, anything else we might need to assign from
  929.           //  can exploit the |nsCOMPtr_helper| facility.
  930.         {
  931.           assign_from_helper(rhs, NS_GET_IID(nsISupports));
  932.           return *this;
  933.         }
  934.       void
  935.       swap( nsCOMPtr<nsISupports>& rhs )
  936.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  937.         {
  938.           nsISupports* temp = rhs.mRawPtr;
  939.           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  940.           NSCAP_LOG_ASSIGNMENT(this, temp);
  941.           NSCAP_LOG_RELEASE(this, mRawPtr);
  942.           NSCAP_LOG_RELEASE(&rhs, temp);
  943.           rhs.mRawPtr = mRawPtr;
  944.           mRawPtr = temp;
  945.         }
  946.       void
  947.       swap( nsISupports*& rhs )
  948.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  949.         {
  950.           nsISupports* temp = rhs;
  951.           NSCAP_LOG_ASSIGNMENT(this, temp);
  952.           NSCAP_LOG_RELEASE(this, mRawPtr);
  953.           rhs = mRawPtr;
  954.           mRawPtr = temp;
  955.         }
  956.         // Other pointer operators
  957.       nsDerivedSafe<nsISupports>*
  958.       get() const
  959.           /*
  960.             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
  961.              Use |get()| _only_ to resolve ambiguity.
  962.             Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
  963.           */
  964.         {
  965.           return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
  966.         }
  967.       operator nsDerivedSafe<nsISupports>*() const
  968.           /*
  969.             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  970.               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
  971.               that makes an |nsCOMPtr| substitutable for a raw pointer.
  972.             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  973.           */
  974.         {
  975.           return get();
  976.         }
  977.       nsDerivedSafe<nsISupports>*
  978.       operator->() const
  979.         {
  980.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  981.           return get();
  982.         }
  983. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  984.   // broken version for IRIX
  985.       nsCOMPtr<nsISupports>*
  986.       get_address() const
  987.           // This is not intended to be used by clients.  See |address_of|
  988.           // below.
  989.         {
  990.           return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
  991.         }
  992. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  993.       nsCOMPtr<nsISupports>*
  994.       get_address()
  995.           // This is not intended to be used by clients.  See |address_of|
  996.           // below.
  997.         {
  998.           return this;
  999.         }
  1000.       const nsCOMPtr<nsISupports>*
  1001.       get_address() const
  1002.           // This is not intended to be used by clients.  See |address_of|
  1003.           // below.
  1004.         {
  1005.           return this;
  1006.         }
  1007. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1008.     public:
  1009.       nsDerivedSafe<nsISupports>&
  1010.       operator*() const
  1011.         {
  1012.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  1013.           return *get();
  1014.         }
  1015. #if 0
  1016.     private:
  1017.       friend class nsGetterAddRefs<nsISupports>;
  1018. #endif
  1019.       nsISupports**
  1020.       StartAssignment()
  1021.         {
  1022. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  1023.           return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
  1024. #else
  1025.           assign_assuming_AddRef(0);
  1026.           return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
  1027. #endif
  1028.         }
  1029.   };
  1030. #ifndef NSCAP_FEATURE_USE_BASE
  1031. template <class T>
  1032. void
  1033. nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
  1034.   {
  1035.     if ( rawPtr )
  1036.       NSCAP_ADDREF(this, rawPtr);
  1037.     assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
  1038.   }
  1039. template <class T>
  1040. void
  1041. nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
  1042.   {
  1043.     T* newRawPtr;
  1044.     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1045.       newRawPtr = 0;
  1046.     assign_assuming_AddRef(newRawPtr);
  1047.   }
  1048. template <class T>
  1049. void
  1050. nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
  1051.   {
  1052.     T* newRawPtr;
  1053.     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1054.       newRawPtr = 0;
  1055.     assign_assuming_AddRef(newRawPtr);
  1056.   }
  1057. template <class T>
  1058. void
  1059. nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
  1060.   {
  1061.     T* newRawPtr;
  1062.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1063.       newRawPtr = 0;
  1064.     assign_assuming_AddRef(newRawPtr);
  1065.   }
  1066. template <class T>
  1067. void
  1068. nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
  1069.   {
  1070.     T* newRawPtr;
  1071.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1072.       newRawPtr = 0;
  1073.     assign_assuming_AddRef(newRawPtr);
  1074.   }
  1075. template <class T>
  1076. void
  1077. nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
  1078.   {
  1079.     T* newRawPtr;
  1080.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1081.       newRawPtr = 0;
  1082.     assign_assuming_AddRef(newRawPtr);
  1083.   }
  1084. template <class T>
  1085. void
  1086. nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
  1087.   {
  1088.     T* newRawPtr;
  1089.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1090.       newRawPtr = 0;
  1091.     assign_assuming_AddRef(newRawPtr);
  1092.   }
  1093. template <class T>
  1094. void
  1095. nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
  1096.   {
  1097.     T* newRawPtr;
  1098.     if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1099.       newRawPtr = 0;
  1100.     assign_assuming_AddRef(newRawPtr);
  1101.   }
  1102. template <class T>
  1103. void**
  1104. nsCOMPtr<T>::begin_assignment()
  1105.   {
  1106.     assign_assuming_AddRef(0);
  1107.     return NS_REINTERPRET_CAST(void**, &mRawPtr);
  1108.   }
  1109. #endif
  1110. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1111. // This is the broken version for IRIX, which can't handle the version below.
  1112. template <class T>
  1113. inline
  1114. nsCOMPtr<T>*
  1115. address_of( const nsCOMPtr<T>& aPtr )
  1116.   {
  1117.     return aPtr.get_address();
  1118.   }
  1119. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1120. template <class T>
  1121. inline
  1122. nsCOMPtr<T>*
  1123. address_of( nsCOMPtr<T>& aPtr )
  1124.   {
  1125.     return aPtr.get_address();
  1126.   }
  1127. template <class T>
  1128. inline
  1129. const nsCOMPtr<T>*
  1130. address_of( const nsCOMPtr<T>& aPtr )
  1131.   {
  1132.     return aPtr.get_address();
  1133.   }
  1134. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1135. template <class T>
  1136. class nsGetterAddRefs
  1137.     /*
  1138.       ...
  1139.       This class is designed to be used for anonymous temporary objects in the
  1140.       argument list of calls that return COM interface pointers, e.g.,
  1141.         nsCOMPtr<IFoo> fooP;
  1142.         ...->QueryInterface(iid, getter_AddRefs(fooP))
  1143.       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
  1144.       When initialized with a |nsCOMPtr|, as in the example above, it returns
  1145.       a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
  1146.       case) can fill in.
  1147.       This type should be a nested class inside |nsCOMPtr<T>|.
  1148.     */
  1149.   {
  1150.     public:
  1151.       explicit
  1152.       nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
  1153.           : mTargetSmartPtr(aSmartPtr)
  1154.         {
  1155.           // nothing else to do
  1156.         }
  1157. #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
  1158.      ~nsGetterAddRefs()
  1159.         {
  1160. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1161.           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1162. #endif
  1163. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  1164.           mTargetSmartPtr.Assert_NoQueryNeeded();
  1165. #endif
  1166.         }
  1167. #endif
  1168.       operator void**()
  1169.         {
  1170.           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1171.         }
  1172.       operator nsISupports**()
  1173.         {
  1174.           return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
  1175.         }
  1176.       operator T**()
  1177.         {
  1178.           return mTargetSmartPtr.StartAssignment();
  1179.         }
  1180.       T*&
  1181.       operator*()
  1182.         {
  1183.           return *(mTargetSmartPtr.StartAssignment());
  1184.         }
  1185.     private:
  1186.       nsCOMPtr<T>& mTargetSmartPtr;
  1187.   };
  1188. NS_SPECIALIZE_TEMPLATE
  1189. class nsGetterAddRefs<nsISupports>
  1190.   {
  1191.     public:
  1192.       explicit
  1193.       nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
  1194.           : mTargetSmartPtr(aSmartPtr)
  1195.         {
  1196.           // nothing else to do
  1197.         }
  1198. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1199.      ~nsGetterAddRefs()
  1200.         {
  1201.           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1202.         }
  1203. #endif
  1204.       operator void**()
  1205.         {
  1206.           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1207.         }
  1208.       operator nsISupports**()
  1209.         {
  1210.           return mTargetSmartPtr.StartAssignment();
  1211.         }
  1212.       nsISupports*&
  1213.       operator*()
  1214.         {
  1215.           return *(mTargetSmartPtr.StartAssignment());
  1216.         }
  1217.     private:
  1218.       nsCOMPtr<nsISupports>& mTargetSmartPtr;
  1219.   };
  1220. template <class T>
  1221. inline
  1222. nsGetterAddRefs<T>
  1223. getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
  1224.     /*
  1225.       Used around a |nsCOMPtr| when 
  1226.       ...makes the class |nsGetterAddRefs<T>| invisible.
  1227.     */
  1228.   {
  1229.     return nsGetterAddRefs<T>(aSmartPtr);
  1230.   }
  1231.   // Comparing two |nsCOMPtr|s
  1232. template <class T, class U>
  1233. inline
  1234. NSCAP_BOOL
  1235. operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1236.   {
  1237.     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
  1238.   }
  1239. template <class T, class U>
  1240. inline
  1241. NSCAP_BOOL
  1242. operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1243.   {
  1244.     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
  1245.   }
  1246.   // Comparing an |nsCOMPtr| to a raw pointer
  1247. template <class T, class U>
  1248. inline
  1249. NSCAP_BOOL
  1250. operator==( const nsCOMPtr<T>& lhs, const U* rhs )
  1251.   {
  1252.     return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
  1253.   }
  1254. template <class T, class U>
  1255. inline
  1256. NSCAP_BOOL
  1257. operator==( const U* lhs, const nsCOMPtr<T>& rhs )
  1258.   {
  1259.     return lhs == NS_STATIC_CAST(const T*, rhs.get());
  1260.   }
  1261. template <class T, class U>
  1262. inline
  1263. NSCAP_BOOL
  1264. operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
  1265.   {
  1266.     return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
  1267.   }
  1268. template <class T, class U>
  1269. inline
  1270. NSCAP_BOOL
  1271. operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
  1272.   {
  1273.     return lhs != NS_STATIC_CAST(const T*, rhs.get());
  1274.   }
  1275.   // To avoid ambiguities caused by the presence of builtin |operator==|s
  1276.   // creating a situation where one of the |operator==| defined above
  1277.   // has a better conversion for one argument and the builtin has a
  1278.   // better conversion for the other argument, define additional
  1279.   // |operator==| without the |const| on the raw pointer.
  1280.   // See bug 65664 for details.
  1281. // This is defined by an autoconf test, but VC++ also has a bug that
  1282. // prevents us from using these.  (It also, fortunately, has the bug
  1283. // that we don't need them either.)
  1284. #if defined(_MSC_VER) && (_MSC_VER < 1310)
  1285. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1286. #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1287. #endif
  1288. #endif
  1289. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1290. template <class T, class U>
  1291. inline
  1292. NSCAP_BOOL
  1293. operator==( const nsCOMPtr<T>& lhs, U* rhs )
  1294.   {
  1295.     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
  1296.   }
  1297. template <class T, class U>
  1298. inline
  1299. NSCAP_BOOL
  1300. operator==( U* lhs, const nsCOMPtr<T>& rhs )
  1301.   {
  1302.     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
  1303.   }
  1304. template <class T, class U>
  1305. inline
  1306. NSCAP_BOOL
  1307. operator!=( const nsCOMPtr<T>& lhs, U* rhs )
  1308.   {
  1309.     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
  1310.   }
  1311. template <class T, class U>
  1312. inline
  1313. NSCAP_BOOL
  1314. operator!=( U* lhs, const nsCOMPtr<T>& rhs )
  1315.   {
  1316.     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
  1317.   }
  1318. #endif
  1319.   // Comparing an |nsCOMPtr| to |0|
  1320. class NSCAP_Zero;
  1321. template <class T>
  1322. inline
  1323. NSCAP_BOOL
  1324. operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1325.     // specifically to allow |smartPtr == 0|
  1326.   {
  1327.     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1328.   }
  1329. template <class T>
  1330. inline
  1331. NSCAP_BOOL
  1332. operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1333.     // specifically to allow |0 == smartPtr|
  1334.   {
  1335.     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1336.   }
  1337. template <class T>
  1338. inline
  1339. NSCAP_BOOL
  1340. operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1341.     // specifically to allow |smartPtr != 0|
  1342.   {
  1343.     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
  1344.   }
  1345. template <class T>
  1346. inline
  1347. NSCAP_BOOL
  1348. operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1349.     // specifically to allow |0 != smartPtr|
  1350.   {
  1351.     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
  1352.   }
  1353. #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
  1354.   // We need to explicitly define comparison operators for `int'
  1355.   // because the compiler is lame.
  1356. template <class T>
  1357. inline
  1358. NSCAP_BOOL
  1359. operator==( const nsCOMPtr<T>& lhs, int rhs )
  1360.     // specifically to allow |smartPtr == 0|
  1361.   {
  1362.     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1363.   }
  1364. template <class T>
  1365. inline
  1366. NSCAP_BOOL
  1367. operator==( int lhs, const nsCOMPtr<T>& rhs )
  1368.     // specifically to allow |0 == smartPtr|
  1369.   {
  1370.     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1371.   }
  1372. #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
  1373.   // Comparing any two [XP]COM objects for identity
  1374. inline
  1375. NSCAP_BOOL
  1376. SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
  1377.   {
  1378.     return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
  1379.   }
  1380. template <class SourceType, class DestinationType>
  1381. inline
  1382. nsresult
  1383. CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
  1384.   {
  1385.     return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  1386.   }
  1387. #endif // !defined(nsCOMPtr_h___)