PageRenderTime 95ms CodeModel.GetById 46ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/gecko_api/include/nsCOMPtr.h

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