Bug 462525 - username truncation code is unnecessarily duplicated in nsLoginManagerP...
[wine-gecko.git] / xpcom / glue / nsCOMPtr.h
blobd2db3f2c50200e9bb8a8986fd64ecac9146c6163
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
23 * Scott Collins <scc@mozilla.org> (original author)
24 * L. David Baron <dbaron@dbaron.org>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsCOMPtr_h___
41 #define nsCOMPtr_h___
44 Having problems?
46 See the User Manual at:
47 http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
50 nsCOMPtr
51 better than a raw pointer
52 for owning objects
53 -- scc
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
63 #ifndef nsISupportsUtils_h__
64 #include "nsISupportsUtils.h"
65 // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
66 #endif
68 #ifndef nscore_h___
69 #include "nscore.h"
70 // for |NS_COM_GLUE|
71 #endif
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.
82 #ifdef _MSC_VER
83 #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
84 // under VC++, we win by inlining StartAssignment
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
92 #define NSCAP_FEATURE_USE_BASE
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
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.
106 #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
107 #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
108 #endif
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.
117 #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
118 #else
119 #define NS_MAY_ALIAS_PTR(t) t*
120 #endif
122 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
123 #define NSCAP_FEATURE_USE_BASE
124 #endif
127 #ifdef HAVE_CPP_BOOL
128 typedef bool NSCAP_BOOL;
129 #else
130 typedef PRBool NSCAP_BOOL;
131 #endif
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
142 #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
143 #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
146 #ifndef NSCAP_ADDREF
147 #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
148 #endif
150 #ifndef NSCAP_RELEASE
151 #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
152 #endif
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
165 #ifndef NSCAP_LOG_RELEASE
166 #define NSCAP_LOG_RELEASE(this, ptr)
167 #endif
169 template <class T>
170 struct already_AddRefed
172 ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
173 |AddRef|ing it. You might want to use this as a return type from a function
174 that produces an already |AddRef|ed pointer as a result.
176 See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
178 This type should be a nested class inside |nsCOMPtr<T>|.
180 Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
181 avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
182 case, and perhaps worth the savings in time and space that its specific
183 implementation affords over the more general solution offered by
184 |nsCOMPtr_helper|.
187 already_AddRefed( T* aRawPtr )
188 : mRawPtr(aRawPtr)
190 // nothing else to do here
193 T* get() const { return mRawPtr; }
195 T* mRawPtr;
198 template <class T>
199 inline
200 const already_AddRefed<T>
201 getter_AddRefs( T* aRawPtr )
203 ...makes typing easier, because it deduces the template type, e.g.,
204 you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
207 return already_AddRefed<T>(aRawPtr);
210 template <class T>
211 inline
212 const already_AddRefed<T>
213 getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
215 return aAlreadyAddRefedPtr;
218 template <class T>
219 inline
220 const already_AddRefed<T>
221 dont_AddRef( T* aRawPtr )
223 return already_AddRefed<T>(aRawPtr);
226 template <class T>
227 inline
228 const already_AddRefed<T>
229 dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
231 return aAlreadyAddRefedPtr;
236 class nsCOMPtr_helper
238 An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
239 that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
240 Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
242 Here are the rules for a helper:
243 - it implements |operator()| to produce an interface pointer
244 - (except for its name) |operator()| is a valid [XP]COM `getter'
245 - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
246 - it matches the type requested with the supplied |nsIID| argument
247 - its constructor provides an optional |nsresult*| that |operator()| can fill
248 in with an error when it is executed
250 See |class nsGetInterface| for an example.
253 public:
254 virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
258 |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
259 avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
260 is called often enough that the codesize savings are big enough to
261 warrant the specialcasing.
264 class
265 NS_COM_GLUE
266 NS_STACK_CLASS
267 NS_FINAL_CLASS
268 nsQueryInterface
270 public:
271 explicit
272 nsQueryInterface( nsISupports* aRawPtr )
273 : mRawPtr(aRawPtr)
275 // nothing else to do here
278 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
280 private:
281 nsISupports* mRawPtr;
284 class NS_COM_GLUE nsQueryInterfaceWithError
286 public:
287 nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
288 : mRawPtr(aRawPtr),
289 mErrorPtr(error)
291 // nothing else to do here
294 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
296 private:
297 nsISupports* mRawPtr;
298 nsresult* mErrorPtr;
301 inline
302 nsQueryInterface
303 do_QueryInterface( nsISupports* aRawPtr )
305 return nsQueryInterface(aRawPtr);
308 inline
309 nsQueryInterfaceWithError
310 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
312 return nsQueryInterfaceWithError(aRawPtr, error);
315 template <class T>
316 inline
317 void
318 do_QueryInterface( already_AddRefed<T>& )
320 // This signature exists solely to _stop_ you from doing the bad thing.
321 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
322 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
325 template <class T>
326 inline
327 void
328 do_QueryInterface( already_AddRefed<T>&, nsresult* )
330 // This signature exists solely to _stop_ you from doing the bad thing.
331 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
332 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
336 ////////////////////////////////////////////////////////////////////////////
337 // Using servicemanager with COMPtrs
338 class NS_COM_GLUE nsGetServiceByCID
340 public:
341 explicit nsGetServiceByCID(const nsCID& aCID)
342 : mCID(aCID)
344 // nothing else to do
347 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
349 private:
350 const nsCID& mCID;
353 class NS_COM_GLUE nsGetServiceByCIDWithError
355 public:
356 nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
357 : mCID(aCID),
358 mErrorPtr(aErrorPtr)
360 // nothing else to do
363 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
365 private:
366 const nsCID& mCID;
367 nsresult* mErrorPtr;
370 class NS_COM_GLUE nsGetServiceByContractID
372 public:
373 explicit nsGetServiceByContractID(const char* aContractID)
374 : mContractID(aContractID)
376 // nothing else to do
379 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
381 private:
382 const char* mContractID;
385 class NS_COM_GLUE nsGetServiceByContractIDWithError
387 public:
388 nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
389 : mContractID(aContractID),
390 mErrorPtr(aErrorPtr)
392 // nothing else to do
395 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
397 private:
398 const char* mContractID;
399 nsresult* mErrorPtr;
402 class
403 nsCOMPtr_base
405 ...factors implementation for all template versions of |nsCOMPtr|.
407 This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
408 because unlike the
410 Here's the way people normally do things like this
412 template <class T> class Foo { ... };
413 template <> class Foo<void*> { ... };
414 template <class T> class Foo<T*> : private Foo<void*> { ... };
417 public:
419 nsCOMPtr_base( nsISupports* rawPtr = 0 )
420 : mRawPtr(rawPtr)
422 // nothing else to do here
425 NS_COM_GLUE NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base();
427 NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* );
428 NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
429 NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
430 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
431 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
432 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
433 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
434 NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
435 NS_COM_GLUE void** NS_FASTCALL begin_assignment();
437 protected:
438 NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
440 void
441 assign_assuming_AddRef( nsISupports* newPtr )
444 |AddRef()|ing the new value (before entering this function) before
445 |Release()|ing the old lets us safely ignore the self-assignment case.
446 We must, however, be careful only to |Release()| _after_ doing the
447 assignment, in case the |Release()| leads to our _own_ destruction,
448 which would, in turn, cause an incorrect second |Release()| of our old
449 pointer. Thank <waterson@netscape.com> for discovering this.
451 nsISupports* oldPtr = mRawPtr;
452 mRawPtr = newPtr;
453 NSCAP_LOG_ASSIGNMENT(this, newPtr);
454 NSCAP_LOG_RELEASE(this, oldPtr);
455 if ( oldPtr )
456 NSCAP_RELEASE(this, oldPtr);
460 // template <class T> class nsGetterAddRefs;
462 template <class T>
463 class
464 NS_FINAL_CLASS
465 nsCOMPtr
466 #ifdef NSCAP_FEATURE_USE_BASE
467 : private nsCOMPtr_base
468 #endif
471 #ifdef NSCAP_FEATURE_USE_BASE
472 #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
473 #else
474 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
476 private:
477 void assign_with_AddRef( nsISupports* );
478 void assign_from_qi( const nsQueryInterface, const nsIID& );
479 void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
480 void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
481 void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
482 void assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
483 void assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
484 void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
485 void** begin_assignment();
487 void
488 assign_assuming_AddRef( T* newPtr )
490 T* oldPtr = mRawPtr;
491 mRawPtr = newPtr;
492 NSCAP_LOG_ASSIGNMENT(this, newPtr);
493 NSCAP_LOG_RELEASE(this, oldPtr);
494 if ( oldPtr )
495 NSCAP_RELEASE(this, oldPtr);
498 private:
499 T* mRawPtr;
500 #endif
502 public:
503 typedef T element_type;
505 #ifndef NSCAP_FEATURE_USE_BASE
506 ~nsCOMPtr()
508 NSCAP_LOG_RELEASE(this, mRawPtr);
509 if ( mRawPtr )
510 NSCAP_RELEASE(this, mRawPtr);
512 #endif
514 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
515 void
516 Assert_NoQueryNeeded()
518 if ( mRawPtr )
520 nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
521 NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
525 #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
526 #else
527 #define NSCAP_ASSERT_NO_QUERY_NEEDED()
528 #endif
531 // Constructors
533 nsCOMPtr()
534 : NSCAP_CTOR_BASE(0)
535 // default constructor
537 NSCAP_LOG_ASSIGNMENT(this, 0);
540 nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
541 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
542 // copy-constructor
544 if ( mRawPtr )
545 NSCAP_ADDREF(this, mRawPtr);
546 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
549 nsCOMPtr( T* aRawPtr )
550 : NSCAP_CTOR_BASE(aRawPtr)
551 // construct from a raw pointer (of the right type)
553 if ( mRawPtr )
554 NSCAP_ADDREF(this, mRawPtr);
555 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
556 NSCAP_ASSERT_NO_QUERY_NEEDED();
559 nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
560 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
561 // construct from |dont_AddRef(expr)|
563 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
564 NSCAP_ASSERT_NO_QUERY_NEEDED();
567 nsCOMPtr( const nsQueryInterface qi )
568 : NSCAP_CTOR_BASE(0)
569 // construct from |do_QueryInterface(expr)|
571 NSCAP_LOG_ASSIGNMENT(this, 0);
572 assign_from_qi(qi, NS_GET_TEMPLATE_IID(T));
575 nsCOMPtr( const nsQueryInterfaceWithError& qi )
576 : NSCAP_CTOR_BASE(0)
577 // construct from |do_QueryInterface(expr, &rv)|
579 NSCAP_LOG_ASSIGNMENT(this, 0);
580 assign_from_qi_with_error(qi, NS_GET_TEMPLATE_IID(T));
583 nsCOMPtr( const nsGetServiceByCID gs )
584 : NSCAP_CTOR_BASE(0)
585 // construct from |do_GetService(cid_expr)|
587 NSCAP_LOG_ASSIGNMENT(this, 0);
588 assign_from_gs_cid(gs, NS_GET_TEMPLATE_IID(T));
591 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
592 : NSCAP_CTOR_BASE(0)
593 // construct from |do_GetService(cid_expr, &rv)|
595 NSCAP_LOG_ASSIGNMENT(this, 0);
596 assign_from_gs_cid_with_error(gs, NS_GET_TEMPLATE_IID(T));
599 nsCOMPtr( const nsGetServiceByContractID gs )
600 : NSCAP_CTOR_BASE(0)
601 // construct from |do_GetService(contractid_expr)|
603 NSCAP_LOG_ASSIGNMENT(this, 0);
604 assign_from_gs_contractid(gs, NS_GET_TEMPLATE_IID(T));
607 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
608 : NSCAP_CTOR_BASE(0)
609 // construct from |do_GetService(contractid_expr, &rv)|
611 NSCAP_LOG_ASSIGNMENT(this, 0);
612 assign_from_gs_contractid_with_error(gs, NS_GET_TEMPLATE_IID(T));
615 nsCOMPtr( const nsCOMPtr_helper& helper )
616 : NSCAP_CTOR_BASE(0)
617 // ...and finally, anything else we might need to construct from
618 // can exploit the |nsCOMPtr_helper| facility
620 NSCAP_LOG_ASSIGNMENT(this, 0);
621 assign_from_helper(helper, NS_GET_TEMPLATE_IID(T));
622 NSCAP_ASSERT_NO_QUERY_NEEDED();
626 // Assignment operators
628 nsCOMPtr<T>&
629 operator=( const nsCOMPtr<T>& rhs )
630 // copy assignment operator
632 assign_with_AddRef(rhs.mRawPtr);
633 return *this;
636 nsCOMPtr<T>&
637 operator=( T* rhs )
638 // assign from a raw pointer (of the right type)
640 assign_with_AddRef(rhs);
641 NSCAP_ASSERT_NO_QUERY_NEEDED();
642 return *this;
645 nsCOMPtr<T>&
646 operator=( const already_AddRefed<T>& rhs )
647 // assign from |dont_AddRef(expr)|
649 assign_assuming_AddRef(rhs.mRawPtr);
650 NSCAP_ASSERT_NO_QUERY_NEEDED();
651 return *this;
654 nsCOMPtr<T>&
655 operator=( const nsQueryInterface rhs )
656 // assign from |do_QueryInterface(expr)|
658 assign_from_qi(rhs, NS_GET_TEMPLATE_IID(T));
659 return *this;
662 nsCOMPtr<T>&
663 operator=( const nsQueryInterfaceWithError& rhs )
664 // assign from |do_QueryInterface(expr, &rv)|
666 assign_from_qi_with_error(rhs, NS_GET_TEMPLATE_IID(T));
667 return *this;
670 nsCOMPtr<T>&
671 operator=( const nsGetServiceByCID rhs )
672 // assign from |do_GetService(cid_expr)|
674 assign_from_gs_cid(rhs, NS_GET_TEMPLATE_IID(T));
675 return *this;
678 nsCOMPtr<T>&
679 operator=( const nsGetServiceByCIDWithError& rhs )
680 // assign from |do_GetService(cid_expr, &rv)|
682 assign_from_gs_cid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
683 return *this;
686 nsCOMPtr<T>&
687 operator=( const nsGetServiceByContractID rhs )
688 // assign from |do_GetService(contractid_expr)|
690 assign_from_gs_contractid(rhs, NS_GET_TEMPLATE_IID(T));
691 return *this;
694 nsCOMPtr<T>&
695 operator=( const nsGetServiceByContractIDWithError& rhs )
696 // assign from |do_GetService(contractid_expr, &rv)|
698 assign_from_gs_contractid_with_error(rhs, NS_GET_TEMPLATE_IID(T));
699 return *this;
702 nsCOMPtr<T>&
703 operator=( const nsCOMPtr_helper& rhs )
704 // ...and finally, anything else we might need to assign from
705 // can exploit the |nsCOMPtr_helper| facility.
707 assign_from_helper(rhs, NS_GET_TEMPLATE_IID(T));
708 NSCAP_ASSERT_NO_QUERY_NEEDED();
709 return *this;
712 void
713 swap( nsCOMPtr<T>& rhs )
714 // ...exchange ownership with |rhs|; can save a pair of refcount operations
716 #ifdef NSCAP_FEATURE_USE_BASE
717 nsISupports* temp = rhs.mRawPtr;
718 #else
719 T* temp = rhs.mRawPtr;
720 #endif
721 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
722 NSCAP_LOG_ASSIGNMENT(this, temp);
723 NSCAP_LOG_RELEASE(this, mRawPtr);
724 NSCAP_LOG_RELEASE(&rhs, temp);
725 rhs.mRawPtr = mRawPtr;
726 mRawPtr = temp;
727 // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
730 void
731 swap( T*& rhs )
732 // ...exchange ownership with |rhs|; can save a pair of refcount operations
734 #ifdef NSCAP_FEATURE_USE_BASE
735 nsISupports* temp = rhs;
736 #else
737 T* temp = rhs;
738 #endif
739 NSCAP_LOG_ASSIGNMENT(this, temp);
740 NSCAP_LOG_RELEASE(this, mRawPtr);
741 rhs = reinterpret_cast<T*>(mRawPtr);
742 mRawPtr = temp;
743 NSCAP_ASSERT_NO_QUERY_NEEDED();
747 // Other pointer operators
749 already_AddRefed<T>
750 forget()
751 // return the value of mRawPtr and null out mRawPtr. Useful for
752 // already_AddRefed return values.
754 T* temp = 0;
755 swap(temp);
756 return temp;
759 void
760 forget( T** rhs )
761 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
762 // Useful to avoid unnecessary AddRef/Release pairs with "out"
763 // parameters.
765 NS_ASSERTION(rhs, "Null pointer passed to forget!");
766 *rhs = 0;
767 swap(*rhs);
771 get() const
773 Prefer the implicit conversion provided automatically by |operator T*() const|.
774 Use |get()| to resolve ambiguity or to get a castable pointer.
777 return reinterpret_cast<T*>(mRawPtr);
780 operator T*() const
782 ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
783 is used in a context where a raw pointer is expected. It is this operator
784 that makes an |nsCOMPtr| substitutable for a raw pointer.
786 Prefer the implicit use of this operator to calling |get()|, except where
787 necessary to resolve ambiguity.
790 return get();
794 operator->() const
796 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
797 return get();
800 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
801 // broken version for IRIX
803 nsCOMPtr<T>*
804 get_address() const
805 // This is not intended to be used by clients. See |address_of|
806 // below.
808 return const_cast<nsCOMPtr<T>*>(this);
811 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
813 nsCOMPtr<T>*
814 get_address()
815 // This is not intended to be used by clients. See |address_of|
816 // below.
818 return this;
821 const nsCOMPtr<T>*
822 get_address() const
823 // This is not intended to be used by clients. See |address_of|
824 // below.
826 return this;
829 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
831 public:
833 operator*() const
835 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
836 return *get();
840 StartAssignment()
842 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
843 return reinterpret_cast<T**>(begin_assignment());
844 #else
845 assign_assuming_AddRef(0);
846 return reinterpret_cast<T**>(&mRawPtr);
847 #endif
854 Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
855 same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
856 to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
857 to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
858 querying ensues. Clients need to be able to pass around arbitrary interface pointers,
859 without hassles, through intermediary code that doesn't know the exact type.
862 NS_SPECIALIZE_TEMPLATE
863 class nsCOMPtr<nsISupports>
864 : private nsCOMPtr_base
866 public:
867 typedef nsISupports element_type;
869 // Constructors
871 nsCOMPtr()
872 : nsCOMPtr_base(0)
873 // default constructor
875 NSCAP_LOG_ASSIGNMENT(this, 0);
878 nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
879 : nsCOMPtr_base(aSmartPtr.mRawPtr)
880 // copy constructor
882 if ( mRawPtr )
883 NSCAP_ADDREF(this, mRawPtr);
884 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
887 nsCOMPtr( nsISupports* aRawPtr )
888 : nsCOMPtr_base(aRawPtr)
889 // construct from a raw pointer (of the right type)
891 if ( mRawPtr )
892 NSCAP_ADDREF(this, mRawPtr);
893 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
896 nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
897 : nsCOMPtr_base(aSmartPtr.mRawPtr)
898 // construct from |dont_AddRef(expr)|
900 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
903 nsCOMPtr( const nsQueryInterface qi )
904 : nsCOMPtr_base(0)
905 // assign from |do_QueryInterface(expr)|
907 NSCAP_LOG_ASSIGNMENT(this, 0);
908 assign_from_qi(qi, NS_GET_IID(nsISupports));
911 nsCOMPtr( const nsQueryInterfaceWithError& qi )
912 : nsCOMPtr_base(0)
913 // assign from |do_QueryInterface(expr, &rv)|
915 NSCAP_LOG_ASSIGNMENT(this, 0);
916 assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
919 nsCOMPtr( const nsGetServiceByCID gs )
920 : nsCOMPtr_base(0)
921 // assign from |do_GetService(cid_expr)|
923 NSCAP_LOG_ASSIGNMENT(this, 0);
924 assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
927 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
928 : nsCOMPtr_base(0)
929 // assign from |do_GetService(cid_expr, &rv)|
931 NSCAP_LOG_ASSIGNMENT(this, 0);
932 assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
935 nsCOMPtr( const nsGetServiceByContractID gs )
936 : nsCOMPtr_base(0)
937 // assign from |do_GetService(contractid_expr)|
939 NSCAP_LOG_ASSIGNMENT(this, 0);
940 assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
943 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
944 : nsCOMPtr_base(0)
945 // assign from |do_GetService(contractid_expr, &rv)|
947 NSCAP_LOG_ASSIGNMENT(this, 0);
948 assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
951 nsCOMPtr( const nsCOMPtr_helper& helper )
952 : nsCOMPtr_base(0)
953 // ...and finally, anything else we might need to construct from
954 // can exploit the |nsCOMPtr_helper| facility
956 NSCAP_LOG_ASSIGNMENT(this, 0);
957 assign_from_helper(helper, NS_GET_IID(nsISupports));
961 // Assignment operators
963 nsCOMPtr<nsISupports>&
964 operator=( const nsCOMPtr<nsISupports>& rhs )
965 // copy assignment operator
967 assign_with_AddRef(rhs.mRawPtr);
968 return *this;
971 nsCOMPtr<nsISupports>&
972 operator=( nsISupports* rhs )
973 // assign from a raw pointer (of the right type)
975 assign_with_AddRef(rhs);
976 return *this;
979 nsCOMPtr<nsISupports>&
980 operator=( const already_AddRefed<nsISupports>& rhs )
981 // assign from |dont_AddRef(expr)|
983 assign_assuming_AddRef(rhs.mRawPtr);
984 return *this;
987 nsCOMPtr<nsISupports>&
988 operator=( const nsQueryInterface rhs )
989 // assign from |do_QueryInterface(expr)|
991 assign_from_qi(rhs, NS_GET_IID(nsISupports));
992 return *this;
995 nsCOMPtr<nsISupports>&
996 operator=( const nsQueryInterfaceWithError& rhs )
997 // assign from |do_QueryInterface(expr, &rv)|
999 assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
1000 return *this;
1003 nsCOMPtr<nsISupports>&
1004 operator=( const nsGetServiceByCID rhs )
1005 // assign from |do_GetService(cid_expr)|
1007 assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
1008 return *this;
1011 nsCOMPtr<nsISupports>&
1012 operator=( const nsGetServiceByCIDWithError& rhs )
1013 // assign from |do_GetService(cid_expr, &rv)|
1015 assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
1016 return *this;
1019 nsCOMPtr<nsISupports>&
1020 operator=( const nsGetServiceByContractID rhs )
1021 // assign from |do_GetService(contractid_expr)|
1023 assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
1024 return *this;
1027 nsCOMPtr<nsISupports>&
1028 operator=( const nsGetServiceByContractIDWithError& rhs )
1029 // assign from |do_GetService(contractid_expr, &rv)|
1031 assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
1032 return *this;
1035 nsCOMPtr<nsISupports>&
1036 operator=( const nsCOMPtr_helper& rhs )
1037 // ...and finally, anything else we might need to assign from
1038 // can exploit the |nsCOMPtr_helper| facility.
1040 assign_from_helper(rhs, NS_GET_IID(nsISupports));
1041 return *this;
1044 void
1045 swap( nsCOMPtr<nsISupports>& rhs )
1046 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1048 nsISupports* temp = rhs.mRawPtr;
1049 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
1050 NSCAP_LOG_ASSIGNMENT(this, temp);
1051 NSCAP_LOG_RELEASE(this, mRawPtr);
1052 NSCAP_LOG_RELEASE(&rhs, temp);
1053 rhs.mRawPtr = mRawPtr;
1054 mRawPtr = temp;
1057 void
1058 swap( nsISupports*& rhs )
1059 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1061 nsISupports* temp = rhs;
1062 NSCAP_LOG_ASSIGNMENT(this, temp);
1063 NSCAP_LOG_RELEASE(this, mRawPtr);
1064 rhs = mRawPtr;
1065 mRawPtr = temp;
1068 void
1069 forget( nsISupports** rhs )
1070 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
1071 // Useful to avoid unnecessary AddRef/Release pairs with "out"
1072 // parameters.
1074 NS_ASSERTION(rhs, "Null pointer passed to forget!");
1075 *rhs = 0;
1076 swap(*rhs);
1079 // Other pointer operators
1081 nsISupports*
1082 get() const
1084 Prefer the implicit conversion provided automatically by
1085 |operator nsISupports*() const|.
1086 Use |get()| to resolve ambiguity or to get a castable pointer.
1089 return reinterpret_cast<nsISupports*>(mRawPtr);
1092 operator nsISupports*() const
1094 ...makes an |nsCOMPtr| act like its underlying raw pointer type whenever it
1095 is used in a context where a raw pointer is expected. It is this operator
1096 that makes an |nsCOMPtr| substitutable for a raw pointer.
1098 Prefer the implicit use of this operator to calling |get()|, except where
1099 necessary to resolve ambiguity.
1102 return get();
1105 nsISupports*
1106 operator->() const
1108 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
1109 return get();
1112 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1113 // broken version for IRIX
1115 nsCOMPtr<nsISupports>*
1116 get_address() const
1117 // This is not intended to be used by clients. See |address_of|
1118 // below.
1120 return const_cast<nsCOMPtr<nsISupports>*>(this);
1123 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1125 nsCOMPtr<nsISupports>*
1126 get_address()
1127 // This is not intended to be used by clients. See |address_of|
1128 // below.
1130 return this;
1133 const nsCOMPtr<nsISupports>*
1134 get_address() const
1135 // This is not intended to be used by clients. See |address_of|
1136 // below.
1138 return this;
1141 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1143 public:
1145 nsISupports&
1146 operator*() const
1148 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
1149 return *get();
1152 nsISupports**
1153 StartAssignment()
1155 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1156 return reinterpret_cast<nsISupports**>(begin_assignment());
1157 #else
1158 assign_assuming_AddRef(0);
1159 return reinterpret_cast<nsISupports**>(&mRawPtr);
1160 #endif
1164 #ifndef NSCAP_FEATURE_USE_BASE
1165 template <class T>
1166 void
1167 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
1169 if ( rawPtr )
1170 NSCAP_ADDREF(this, rawPtr);
1171 assign_assuming_AddRef(reinterpret_cast<T*>(rawPtr));
1174 template <class T>
1175 void
1176 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
1178 void* newRawPtr;
1179 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1180 newRawPtr = 0;
1181 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1184 template <class T>
1185 void
1186 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
1188 void* newRawPtr;
1189 if ( NS_FAILED( qi(aIID, &newRawPtr) ) )
1190 newRawPtr = 0;
1191 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1194 template <class T>
1195 void
1196 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
1198 void* newRawPtr;
1199 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1200 newRawPtr = 0;
1201 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1204 template <class T>
1205 void
1206 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
1208 void* newRawPtr;
1209 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1210 newRawPtr = 0;
1211 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1214 template <class T>
1215 void
1216 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
1218 void* newRawPtr;
1219 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1220 newRawPtr = 0;
1221 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1224 template <class T>
1225 void
1226 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
1228 void* newRawPtr;
1229 if ( NS_FAILED( gs(aIID, &newRawPtr) ) )
1230 newRawPtr = 0;
1231 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1234 template <class T>
1235 void
1236 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
1238 void* newRawPtr;
1239 if ( NS_FAILED( helper(aIID, &newRawPtr) ) )
1240 newRawPtr = 0;
1241 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
1244 template <class T>
1245 void**
1246 nsCOMPtr<T>::begin_assignment()
1248 assign_assuming_AddRef(0);
1249 union { T** mT; void** mVoid; } result;
1250 result.mT = &mRawPtr;
1251 return result.mVoid;
1253 #endif
1255 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1257 // This is the broken version for IRIX, which can't handle the version below.
1259 template <class T>
1260 inline
1261 nsCOMPtr<T>*
1262 address_of( const nsCOMPtr<T>& aPtr )
1264 return aPtr.get_address();
1267 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1269 template <class T>
1270 inline
1271 nsCOMPtr<T>*
1272 address_of( nsCOMPtr<T>& aPtr )
1274 return aPtr.get_address();
1277 template <class T>
1278 inline
1279 const nsCOMPtr<T>*
1280 address_of( const nsCOMPtr<T>& aPtr )
1282 return aPtr.get_address();
1285 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1287 template <class T>
1288 class nsGetterAddRefs
1292 This class is designed to be used for anonymous temporary objects in the
1293 argument list of calls that return COM interface pointers, e.g.,
1295 nsCOMPtr<IFoo> fooP;
1296 ...->QueryInterface(iid, getter_AddRefs(fooP))
1298 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1300 When initialized with a |nsCOMPtr|, as in the example above, it returns
1301 a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
1302 case) can fill in.
1304 This type should be a nested class inside |nsCOMPtr<T>|.
1307 public:
1308 explicit
1309 nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
1310 : mTargetSmartPtr(aSmartPtr)
1312 // nothing else to do
1315 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
1316 ~nsGetterAddRefs()
1318 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1319 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1320 #endif
1322 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1323 mTargetSmartPtr.Assert_NoQueryNeeded();
1324 #endif
1326 #endif
1328 operator void**()
1330 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1333 operator nsISupports**()
1335 return reinterpret_cast<nsISupports**>(mTargetSmartPtr.StartAssignment());
1338 operator T**()
1340 return mTargetSmartPtr.StartAssignment();
1344 operator*()
1346 return *(mTargetSmartPtr.StartAssignment());
1349 private:
1350 nsCOMPtr<T>& mTargetSmartPtr;
1354 NS_SPECIALIZE_TEMPLATE
1355 class nsGetterAddRefs<nsISupports>
1357 public:
1358 explicit
1359 nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
1360 : mTargetSmartPtr(aSmartPtr)
1362 // nothing else to do
1365 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1366 ~nsGetterAddRefs()
1368 NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void *>(address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1370 #endif
1372 operator void**()
1374 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1377 operator nsISupports**()
1379 return mTargetSmartPtr.StartAssignment();
1382 nsISupports*&
1383 operator*()
1385 return *(mTargetSmartPtr.StartAssignment());
1388 private:
1389 nsCOMPtr<nsISupports>& mTargetSmartPtr;
1393 template <class T>
1394 inline
1395 nsGetterAddRefs<T>
1396 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
1398 Used around a |nsCOMPtr| when
1399 ...makes the class |nsGetterAddRefs<T>| invisible.
1402 return nsGetterAddRefs<T>(aSmartPtr);
1407 // Comparing two |nsCOMPtr|s
1409 template <class T, class U>
1410 inline
1411 NSCAP_BOOL
1412 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1414 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
1418 template <class T, class U>
1419 inline
1420 NSCAP_BOOL
1421 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1423 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
1427 // Comparing an |nsCOMPtr| to a raw pointer
1429 template <class T, class U>
1430 inline
1431 NSCAP_BOOL
1432 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
1434 return static_cast<const T*>(lhs.get()) == rhs;
1437 template <class T, class U>
1438 inline
1439 NSCAP_BOOL
1440 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
1442 return lhs == static_cast<const T*>(rhs.get());
1445 template <class T, class U>
1446 inline
1447 NSCAP_BOOL
1448 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
1450 return static_cast<const T*>(lhs.get()) != rhs;
1453 template <class T, class U>
1454 inline
1455 NSCAP_BOOL
1456 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
1458 return lhs != static_cast<const T*>(rhs.get());
1461 // To avoid ambiguities caused by the presence of builtin |operator==|s
1462 // creating a situation where one of the |operator==| defined above
1463 // has a better conversion for one argument and the builtin has a
1464 // better conversion for the other argument, define additional
1465 // |operator==| without the |const| on the raw pointer.
1466 // See bug 65664 for details.
1468 // This is defined by an autoconf test, but VC++ also has a bug that
1469 // prevents us from using these. (It also, fortunately, has the bug
1470 // that we don't need them either.)
1471 #if defined(_MSC_VER) && (_MSC_VER < 1310)
1472 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1473 #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1474 #endif
1475 #endif
1477 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1478 template <class T, class U>
1479 inline
1480 NSCAP_BOOL
1481 operator==( const nsCOMPtr<T>& lhs, U* rhs )
1483 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
1486 template <class T, class U>
1487 inline
1488 NSCAP_BOOL
1489 operator==( U* lhs, const nsCOMPtr<T>& rhs )
1491 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
1494 template <class T, class U>
1495 inline
1496 NSCAP_BOOL
1497 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
1499 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
1502 template <class T, class U>
1503 inline
1504 NSCAP_BOOL
1505 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
1507 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
1509 #endif
1513 // Comparing an |nsCOMPtr| to |0|
1515 class NSCAP_Zero;
1517 template <class T>
1518 inline
1519 NSCAP_BOOL
1520 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1521 // specifically to allow |smartPtr == 0|
1523 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1526 template <class T>
1527 inline
1528 NSCAP_BOOL
1529 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1530 // specifically to allow |0 == smartPtr|
1532 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1535 template <class T>
1536 inline
1537 NSCAP_BOOL
1538 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1539 // specifically to allow |smartPtr != 0|
1541 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
1544 template <class T>
1545 inline
1546 NSCAP_BOOL
1547 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1548 // specifically to allow |0 != smartPtr|
1550 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
1554 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1556 // We need to explicitly define comparison operators for `int'
1557 // because the compiler is lame.
1559 template <class T>
1560 inline
1561 NSCAP_BOOL
1562 operator==( const nsCOMPtr<T>& lhs, int rhs )
1563 // specifically to allow |smartPtr == 0|
1565 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1568 template <class T>
1569 inline
1570 NSCAP_BOOL
1571 operator==( int lhs, const nsCOMPtr<T>& rhs )
1572 // specifically to allow |0 == smartPtr|
1574 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1577 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1579 // Comparing any two [XP]COM objects for identity
1581 inline
1582 NSCAP_BOOL
1583 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
1585 return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
1590 template <class SourceType, class DestinationType>
1591 inline
1592 nsresult
1593 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
1595 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1598 #endif // !defined(nsCOMPtr_h___)