xpcom/glue/nsCOMPtr.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial