LCOV - app.info - objdir/dist/include/nsCOMPtr.h

LCOV - code coverage report
| Current view: | directory - objdir/dist/include - nsCOMPtr.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 71 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 53 | 0 | 0.0 %

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

Generated by: LCOV version 1.7