xpcom/base/nsAutoPtr.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 nsAutoPtr_h___
michael@0 7 #define nsAutoPtr_h___
michael@0 8
michael@0 9 #include "nsCOMPtr.h"
michael@0 10
michael@0 11 #include "nsCycleCollectionNoteChild.h"
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13
michael@0 14 /*****************************************************************************/
michael@0 15
michael@0 16 // template <class T> class nsAutoPtrGetterTransfers;
michael@0 17
michael@0 18 template <class T>
michael@0 19 class nsAutoPtr
michael@0 20 {
michael@0 21 private:
michael@0 22 void**
michael@0 23 begin_assignment()
michael@0 24 {
michael@0 25 assign(0);
michael@0 26 return reinterpret_cast<void**>(&mRawPtr);
michael@0 27 }
michael@0 28
michael@0 29 void
michael@0 30 assign( T* newPtr )
michael@0 31 {
michael@0 32 T* oldPtr = mRawPtr;
michael@0 33
michael@0 34 if (newPtr != nullptr && newPtr == oldPtr) {
michael@0 35 NS_RUNTIMEABORT("Logic flaw in the caller");
michael@0 36 }
michael@0 37
michael@0 38 mRawPtr = newPtr;
michael@0 39 delete oldPtr;
michael@0 40 }
michael@0 41
michael@0 42 // |class Ptr| helps us prevent implicit "copy construction"
michael@0 43 // through |operator T*() const| from a |const nsAutoPtr<T>|
michael@0 44 // because two implicit conversions in a row aren't allowed.
michael@0 45 // It still allows assignment from T* through implicit conversion
michael@0 46 // from |T*| to |nsAutoPtr<T>::Ptr|
michael@0 47 class Ptr
michael@0 48 {
michael@0 49 public:
michael@0 50 Ptr( T* aPtr )
michael@0 51 : mPtr(aPtr)
michael@0 52 {
michael@0 53 }
michael@0 54
michael@0 55 operator T*() const
michael@0 56 {
michael@0 57 return mPtr;
michael@0 58 }
michael@0 59
michael@0 60 private:
michael@0 61 T* mPtr;
michael@0 62 };
michael@0 63
michael@0 64 private:
michael@0 65 T* mRawPtr;
michael@0 66
michael@0 67 public:
michael@0 68 typedef T element_type;
michael@0 69
michael@0 70 ~nsAutoPtr()
michael@0 71 {
michael@0 72 delete mRawPtr;
michael@0 73 }
michael@0 74
michael@0 75 // Constructors
michael@0 76
michael@0 77 nsAutoPtr()
michael@0 78 : mRawPtr(0)
michael@0 79 // default constructor
michael@0 80 {
michael@0 81 }
michael@0 82
michael@0 83 nsAutoPtr( Ptr aRawPtr )
michael@0 84 : mRawPtr(aRawPtr)
michael@0 85 // construct from a raw pointer (of the right type)
michael@0 86 {
michael@0 87 }
michael@0 88
michael@0 89 // This constructor shouldn't exist; we should just use the &&
michael@0 90 // constructor.
michael@0 91 nsAutoPtr( nsAutoPtr<T>& aSmartPtr )
michael@0 92 : mRawPtr( aSmartPtr.forget() )
michael@0 93 // Construct by transferring ownership from another smart pointer.
michael@0 94 {
michael@0 95 }
michael@0 96
michael@0 97 nsAutoPtr( nsAutoPtr<T>&& aSmartPtr )
michael@0 98 : mRawPtr( aSmartPtr.forget() )
michael@0 99 // Construct by transferring ownership from another smart pointer.
michael@0 100 {
michael@0 101 }
michael@0 102
michael@0 103 // Assignment operators
michael@0 104
michael@0 105 nsAutoPtr<T>&
michael@0 106 operator=( T* rhs )
michael@0 107 // assign from a raw pointer (of the right type)
michael@0 108 {
michael@0 109 assign(rhs);
michael@0 110 return *this;
michael@0 111 }
michael@0 112
michael@0 113 nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs )
michael@0 114 // assign by transferring ownership from another smart pointer.
michael@0 115 {
michael@0 116 assign(rhs.forget());
michael@0 117 return *this;
michael@0 118 }
michael@0 119
michael@0 120 // Other pointer operators
michael@0 121
michael@0 122 T*
michael@0 123 get() const
michael@0 124 /*
michael@0 125 Prefer the implicit conversion provided automatically by
michael@0 126 |operator T*() const|. Use |get()| _only_ to resolve
michael@0 127 ambiguity.
michael@0 128 */
michael@0 129 {
michael@0 130 return mRawPtr;
michael@0 131 }
michael@0 132
michael@0 133 operator T*() const
michael@0 134 /*
michael@0 135 ...makes an |nsAutoPtr| act like its underlying raw pointer
michael@0 136 type whenever it is used in a context where a raw pointer
michael@0 137 is expected. It is this operator that makes an |nsAutoPtr|
michael@0 138 substitutable for a raw pointer.
michael@0 139
michael@0 140 Prefer the implicit use of this operator to calling |get()|,
michael@0 141 except where necessary to resolve ambiguity.
michael@0 142 */
michael@0 143 {
michael@0 144 return get();
michael@0 145 }
michael@0 146
michael@0 147 T*
michael@0 148 forget()
michael@0 149 {
michael@0 150 T* temp = mRawPtr;
michael@0 151 mRawPtr = 0;
michael@0 152 return temp;
michael@0 153 }
michael@0 154
michael@0 155 T*
michael@0 156 operator->() const
michael@0 157 {
michael@0 158 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
michael@0 159 return get();
michael@0 160 }
michael@0 161
michael@0 162 // This operator is needed for gcc <= 4.0.* and for Sun Studio; it
michael@0 163 // causes internal compiler errors for some MSVC versions. (It's not
michael@0 164 // clear to me whether it should be needed.)
michael@0 165 #ifndef _MSC_VER
michael@0 166 template <class U, class V>
michael@0 167 U&
michael@0 168 operator->*(U V::* aMember)
michael@0 169 {
michael@0 170 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->*().");
michael@0 171 return get()->*aMember;
michael@0 172 }
michael@0 173 #endif
michael@0 174
michael@0 175 nsAutoPtr<T>*
michael@0 176 get_address()
michael@0 177 // This is not intended to be used by clients. See |address_of|
michael@0 178 // below.
michael@0 179 {
michael@0 180 return this;
michael@0 181 }
michael@0 182
michael@0 183 const nsAutoPtr<T>*
michael@0 184 get_address() const
michael@0 185 // This is not intended to be used by clients. See |address_of|
michael@0 186 // below.
michael@0 187 {
michael@0 188 return this;
michael@0 189 }
michael@0 190
michael@0 191 public:
michael@0 192 T&
michael@0 193 operator*() const
michael@0 194 {
michael@0 195 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*().");
michael@0 196 return *get();
michael@0 197 }
michael@0 198
michael@0 199 T**
michael@0 200 StartAssignment()
michael@0 201 {
michael@0 202 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
michael@0 203 return reinterpret_cast<T**>(begin_assignment());
michael@0 204 #else
michael@0 205 assign(0);
michael@0 206 return reinterpret_cast<T**>(&mRawPtr);
michael@0 207 #endif
michael@0 208 }
michael@0 209 };
michael@0 210
michael@0 211 template <class T>
michael@0 212 inline
michael@0 213 nsAutoPtr<T>*
michael@0 214 address_of( nsAutoPtr<T>& aPtr )
michael@0 215 {
michael@0 216 return aPtr.get_address();
michael@0 217 }
michael@0 218
michael@0 219 template <class T>
michael@0 220 inline
michael@0 221 const nsAutoPtr<T>*
michael@0 222 address_of( const nsAutoPtr<T>& aPtr )
michael@0 223 {
michael@0 224 return aPtr.get_address();
michael@0 225 }
michael@0 226
michael@0 227 template <class T>
michael@0 228 class nsAutoPtrGetterTransfers
michael@0 229 /*
michael@0 230 ...
michael@0 231
michael@0 232 This class is designed to be used for anonymous temporary objects in the
michael@0 233 argument list of calls that return COM interface pointers, e.g.,
michael@0 234
michael@0 235 nsAutoPtr<IFoo> fooP;
michael@0 236 ...->GetTransferedPointer(getter_Transfers(fooP))
michael@0 237
michael@0 238 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
michael@0 239
michael@0 240 When initialized with a |nsAutoPtr|, as in the example above, it returns
michael@0 241 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
michael@0 242 outer call (|GetTransferedPointer| in this case) can fill in.
michael@0 243
michael@0 244 This type should be a nested class inside |nsAutoPtr<T>|.
michael@0 245 */
michael@0 246 {
michael@0 247 public:
michael@0 248 explicit
michael@0 249 nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr )
michael@0 250 : mTargetSmartPtr(aSmartPtr)
michael@0 251 {
michael@0 252 // nothing else to do
michael@0 253 }
michael@0 254
michael@0 255 operator void**()
michael@0 256 {
michael@0 257 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
michael@0 258 }
michael@0 259
michael@0 260 operator T**()
michael@0 261 {
michael@0 262 return mTargetSmartPtr.StartAssignment();
michael@0 263 }
michael@0 264
michael@0 265 T*&
michael@0 266 operator*()
michael@0 267 {
michael@0 268 return *(mTargetSmartPtr.StartAssignment());
michael@0 269 }
michael@0 270
michael@0 271 private:
michael@0 272 nsAutoPtr<T>& mTargetSmartPtr;
michael@0 273 };
michael@0 274
michael@0 275 template <class T>
michael@0 276 inline
michael@0 277 nsAutoPtrGetterTransfers<T>
michael@0 278 getter_Transfers( nsAutoPtr<T>& aSmartPtr )
michael@0 279 /*
michael@0 280 Used around a |nsAutoPtr| when
michael@0 281 ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
michael@0 282 */
michael@0 283 {
michael@0 284 return nsAutoPtrGetterTransfers<T>(aSmartPtr);
michael@0 285 }
michael@0 286
michael@0 287
michael@0 288
michael@0 289 // Comparing two |nsAutoPtr|s
michael@0 290
michael@0 291 template <class T, class U>
michael@0 292 inline
michael@0 293 bool
michael@0 294 operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
michael@0 295 {
michael@0 296 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
michael@0 297 }
michael@0 298
michael@0 299
michael@0 300 template <class T, class U>
michael@0 301 inline
michael@0 302 bool
michael@0 303 operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
michael@0 304 {
michael@0 305 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
michael@0 306 }
michael@0 307
michael@0 308
michael@0 309 // Comparing an |nsAutoPtr| to a raw pointer
michael@0 310
michael@0 311 template <class T, class U>
michael@0 312 inline
michael@0 313 bool
michael@0 314 operator==( const nsAutoPtr<T>& lhs, const U* rhs )
michael@0 315 {
michael@0 316 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
michael@0 317 }
michael@0 318
michael@0 319 template <class T, class U>
michael@0 320 inline
michael@0 321 bool
michael@0 322 operator==( const U* lhs, const nsAutoPtr<T>& rhs )
michael@0 323 {
michael@0 324 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 325 }
michael@0 326
michael@0 327 template <class T, class U>
michael@0 328 inline
michael@0 329 bool
michael@0 330 operator!=( const nsAutoPtr<T>& lhs, const U* rhs )
michael@0 331 {
michael@0 332 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
michael@0 333 }
michael@0 334
michael@0 335 template <class T, class U>
michael@0 336 inline
michael@0 337 bool
michael@0 338 operator!=( const U* lhs, const nsAutoPtr<T>& rhs )
michael@0 339 {
michael@0 340 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 341 }
michael@0 342
michael@0 343 // To avoid ambiguities caused by the presence of builtin |operator==|s
michael@0 344 // creating a situation where one of the |operator==| defined above
michael@0 345 // has a better conversion for one argument and the builtin has a
michael@0 346 // better conversion for the other argument, define additional
michael@0 347 // |operator==| without the |const| on the raw pointer.
michael@0 348 // See bug 65664 for details.
michael@0 349
michael@0 350 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
michael@0 351 template <class T, class U>
michael@0 352 inline
michael@0 353 bool
michael@0 354 operator==( const nsAutoPtr<T>& lhs, U* rhs )
michael@0 355 {
michael@0 356 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
michael@0 357 }
michael@0 358
michael@0 359 template <class T, class U>
michael@0 360 inline
michael@0 361 bool
michael@0 362 operator==( U* lhs, const nsAutoPtr<T>& rhs )
michael@0 363 {
michael@0 364 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 365 }
michael@0 366
michael@0 367 template <class T, class U>
michael@0 368 inline
michael@0 369 bool
michael@0 370 operator!=( const nsAutoPtr<T>& lhs, U* rhs )
michael@0 371 {
michael@0 372 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
michael@0 373 }
michael@0 374
michael@0 375 template <class T, class U>
michael@0 376 inline
michael@0 377 bool
michael@0 378 operator!=( U* lhs, const nsAutoPtr<T>& rhs )
michael@0 379 {
michael@0 380 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 381 }
michael@0 382 #endif
michael@0 383
michael@0 384
michael@0 385
michael@0 386 // Comparing an |nsAutoPtr| to |0|
michael@0 387
michael@0 388 template <class T>
michael@0 389 inline
michael@0 390 bool
michael@0 391 operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 392 // specifically to allow |smartPtr == 0|
michael@0 393 {
michael@0 394 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 395 }
michael@0 396
michael@0 397 template <class T>
michael@0 398 inline
michael@0 399 bool
michael@0 400 operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
michael@0 401 // specifically to allow |0 == smartPtr|
michael@0 402 {
michael@0 403 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 404 }
michael@0 405
michael@0 406 template <class T>
michael@0 407 inline
michael@0 408 bool
michael@0 409 operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 410 // specifically to allow |smartPtr != 0|
michael@0 411 {
michael@0 412 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
michael@0 413 }
michael@0 414
michael@0 415 template <class T>
michael@0 416 inline
michael@0 417 bool
michael@0 418 operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
michael@0 419 // specifically to allow |0 != smartPtr|
michael@0 420 {
michael@0 421 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
michael@0 422 }
michael@0 423
michael@0 424
michael@0 425 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
michael@0 426
michael@0 427 // We need to explicitly define comparison operators for `int'
michael@0 428 // because the compiler is lame.
michael@0 429
michael@0 430 template <class T>
michael@0 431 inline
michael@0 432 bool
michael@0 433 operator==( const nsAutoPtr<T>& lhs, int rhs )
michael@0 434 // specifically to allow |smartPtr == 0|
michael@0 435 {
michael@0 436 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 437 }
michael@0 438
michael@0 439 template <class T>
michael@0 440 inline
michael@0 441 bool
michael@0 442 operator==( int lhs, const nsAutoPtr<T>& rhs )
michael@0 443 // specifically to allow |0 == smartPtr|
michael@0 444 {
michael@0 445 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 446 }
michael@0 447
michael@0 448 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
michael@0 449
michael@0 450 /*****************************************************************************/
michael@0 451
michael@0 452 // template <class T> class nsAutoArrayPtrGetterTransfers;
michael@0 453
michael@0 454 template <class T>
michael@0 455 class nsAutoArrayPtr
michael@0 456 {
michael@0 457 private:
michael@0 458 void**
michael@0 459 begin_assignment()
michael@0 460 {
michael@0 461 assign(0);
michael@0 462 return reinterpret_cast<void**>(&mRawPtr);
michael@0 463 }
michael@0 464
michael@0 465 void
michael@0 466 assign( T* newPtr )
michael@0 467 {
michael@0 468 T* oldPtr = mRawPtr;
michael@0 469 mRawPtr = newPtr;
michael@0 470 delete [] oldPtr;
michael@0 471 }
michael@0 472
michael@0 473 private:
michael@0 474 T* mRawPtr;
michael@0 475
michael@0 476 public:
michael@0 477 typedef T element_type;
michael@0 478
michael@0 479 ~nsAutoArrayPtr()
michael@0 480 {
michael@0 481 delete [] mRawPtr;
michael@0 482 }
michael@0 483
michael@0 484 // Constructors
michael@0 485
michael@0 486 nsAutoArrayPtr()
michael@0 487 : mRawPtr(0)
michael@0 488 // default constructor
michael@0 489 {
michael@0 490 }
michael@0 491
michael@0 492 nsAutoArrayPtr( T* aRawPtr )
michael@0 493 : mRawPtr(aRawPtr)
michael@0 494 // construct from a raw pointer (of the right type)
michael@0 495 {
michael@0 496 }
michael@0 497
michael@0 498 nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
michael@0 499 : mRawPtr( aSmartPtr.forget() )
michael@0 500 // Construct by transferring ownership from another smart pointer.
michael@0 501 {
michael@0 502 }
michael@0 503
michael@0 504
michael@0 505 // Assignment operators
michael@0 506
michael@0 507 nsAutoArrayPtr<T>&
michael@0 508 operator=( T* rhs )
michael@0 509 // assign from a raw pointer (of the right type)
michael@0 510 {
michael@0 511 assign(rhs);
michael@0 512 return *this;
michael@0 513 }
michael@0 514
michael@0 515 nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs )
michael@0 516 // assign by transferring ownership from another smart pointer.
michael@0 517 {
michael@0 518 assign(rhs.forget());
michael@0 519 return *this;
michael@0 520 }
michael@0 521
michael@0 522 // Other pointer operators
michael@0 523
michael@0 524 T*
michael@0 525 get() const
michael@0 526 /*
michael@0 527 Prefer the implicit conversion provided automatically by
michael@0 528 |operator T*() const|. Use |get()| _only_ to resolve
michael@0 529 ambiguity.
michael@0 530 */
michael@0 531 {
michael@0 532 return mRawPtr;
michael@0 533 }
michael@0 534
michael@0 535 operator T*() const
michael@0 536 /*
michael@0 537 ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
michael@0 538 type whenever it is used in a context where a raw pointer
michael@0 539 is expected. It is this operator that makes an |nsAutoArrayPtr|
michael@0 540 substitutable for a raw pointer.
michael@0 541
michael@0 542 Prefer the implicit use of this operator to calling |get()|,
michael@0 543 except where necessary to resolve ambiguity.
michael@0 544 */
michael@0 545 {
michael@0 546 return get();
michael@0 547 }
michael@0 548
michael@0 549 T*
michael@0 550 forget()
michael@0 551 {
michael@0 552 T* temp = mRawPtr;
michael@0 553 mRawPtr = 0;
michael@0 554 return temp;
michael@0 555 }
michael@0 556
michael@0 557 T*
michael@0 558 operator->() const
michael@0 559 {
michael@0 560 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
michael@0 561 return get();
michael@0 562 }
michael@0 563
michael@0 564 nsAutoArrayPtr<T>*
michael@0 565 get_address()
michael@0 566 // This is not intended to be used by clients. See |address_of|
michael@0 567 // below.
michael@0 568 {
michael@0 569 return this;
michael@0 570 }
michael@0 571
michael@0 572 const nsAutoArrayPtr<T>*
michael@0 573 get_address() const
michael@0 574 // This is not intended to be used by clients. See |address_of|
michael@0 575 // below.
michael@0 576 {
michael@0 577 return this;
michael@0 578 }
michael@0 579
michael@0 580 public:
michael@0 581 T&
michael@0 582 operator*() const
michael@0 583 {
michael@0 584 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*().");
michael@0 585 return *get();
michael@0 586 }
michael@0 587
michael@0 588 T**
michael@0 589 StartAssignment()
michael@0 590 {
michael@0 591 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
michael@0 592 return reinterpret_cast<T**>(begin_assignment());
michael@0 593 #else
michael@0 594 assign(0);
michael@0 595 return reinterpret_cast<T**>(&mRawPtr);
michael@0 596 #endif
michael@0 597 }
michael@0 598
michael@0 599 size_t
michael@0 600 SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 601 {
michael@0 602 return aMallocSizeOf(mRawPtr);
michael@0 603 }
michael@0 604
michael@0 605 size_t
michael@0 606 SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 607 {
michael@0 608 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
michael@0 609 }
michael@0 610 };
michael@0 611
michael@0 612 template <class T>
michael@0 613 inline
michael@0 614 nsAutoArrayPtr<T>*
michael@0 615 address_of( nsAutoArrayPtr<T>& aPtr )
michael@0 616 {
michael@0 617 return aPtr.get_address();
michael@0 618 }
michael@0 619
michael@0 620 template <class T>
michael@0 621 inline
michael@0 622 const nsAutoArrayPtr<T>*
michael@0 623 address_of( const nsAutoArrayPtr<T>& aPtr )
michael@0 624 {
michael@0 625 return aPtr.get_address();
michael@0 626 }
michael@0 627
michael@0 628 template <class T>
michael@0 629 class nsAutoArrayPtrGetterTransfers
michael@0 630 /*
michael@0 631 ...
michael@0 632
michael@0 633 This class is designed to be used for anonymous temporary objects in the
michael@0 634 argument list of calls that return COM interface pointers, e.g.,
michael@0 635
michael@0 636 nsAutoArrayPtr<IFoo> fooP;
michael@0 637 ...->GetTransferedPointer(getter_Transfers(fooP))
michael@0 638
michael@0 639 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
michael@0 640
michael@0 641 When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
michael@0 642 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
michael@0 643 outer call (|GetTransferedPointer| in this case) can fill in.
michael@0 644
michael@0 645 This type should be a nested class inside |nsAutoArrayPtr<T>|.
michael@0 646 */
michael@0 647 {
michael@0 648 public:
michael@0 649 explicit
michael@0 650 nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr )
michael@0 651 : mTargetSmartPtr(aSmartPtr)
michael@0 652 {
michael@0 653 // nothing else to do
michael@0 654 }
michael@0 655
michael@0 656 operator void**()
michael@0 657 {
michael@0 658 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
michael@0 659 }
michael@0 660
michael@0 661 operator T**()
michael@0 662 {
michael@0 663 return mTargetSmartPtr.StartAssignment();
michael@0 664 }
michael@0 665
michael@0 666 T*&
michael@0 667 operator*()
michael@0 668 {
michael@0 669 return *(mTargetSmartPtr.StartAssignment());
michael@0 670 }
michael@0 671
michael@0 672 private:
michael@0 673 nsAutoArrayPtr<T>& mTargetSmartPtr;
michael@0 674 };
michael@0 675
michael@0 676 template <class T>
michael@0 677 inline
michael@0 678 nsAutoArrayPtrGetterTransfers<T>
michael@0 679 getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr )
michael@0 680 /*
michael@0 681 Used around a |nsAutoArrayPtr| when
michael@0 682 ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
michael@0 683 */
michael@0 684 {
michael@0 685 return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
michael@0 686 }
michael@0 687
michael@0 688
michael@0 689
michael@0 690 // Comparing two |nsAutoArrayPtr|s
michael@0 691
michael@0 692 template <class T, class U>
michael@0 693 inline
michael@0 694 bool
michael@0 695 operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
michael@0 696 {
michael@0 697 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
michael@0 698 }
michael@0 699
michael@0 700
michael@0 701 template <class T, class U>
michael@0 702 inline
michael@0 703 bool
michael@0 704 operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
michael@0 705 {
michael@0 706 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
michael@0 707 }
michael@0 708
michael@0 709
michael@0 710 // Comparing an |nsAutoArrayPtr| to a raw pointer
michael@0 711
michael@0 712 template <class T, class U>
michael@0 713 inline
michael@0 714 bool
michael@0 715 operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs )
michael@0 716 {
michael@0 717 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
michael@0 718 }
michael@0 719
michael@0 720 template <class T, class U>
michael@0 721 inline
michael@0 722 bool
michael@0 723 operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 724 {
michael@0 725 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 726 }
michael@0 727
michael@0 728 template <class T, class U>
michael@0 729 inline
michael@0 730 bool
michael@0 731 operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs )
michael@0 732 {
michael@0 733 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
michael@0 734 }
michael@0 735
michael@0 736 template <class T, class U>
michael@0 737 inline
michael@0 738 bool
michael@0 739 operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 740 {
michael@0 741 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 742 }
michael@0 743
michael@0 744 // To avoid ambiguities caused by the presence of builtin |operator==|s
michael@0 745 // creating a situation where one of the |operator==| defined above
michael@0 746 // has a better conversion for one argument and the builtin has a
michael@0 747 // better conversion for the other argument, define additional
michael@0 748 // |operator==| without the |const| on the raw pointer.
michael@0 749 // See bug 65664 for details.
michael@0 750
michael@0 751 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
michael@0 752 template <class T, class U>
michael@0 753 inline
michael@0 754 bool
michael@0 755 operator==( const nsAutoArrayPtr<T>& lhs, U* rhs )
michael@0 756 {
michael@0 757 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
michael@0 758 }
michael@0 759
michael@0 760 template <class T, class U>
michael@0 761 inline
michael@0 762 bool
michael@0 763 operator==( U* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 764 {
michael@0 765 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 766 }
michael@0 767
michael@0 768 template <class T, class U>
michael@0 769 inline
michael@0 770 bool
michael@0 771 operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs )
michael@0 772 {
michael@0 773 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
michael@0 774 }
michael@0 775
michael@0 776 template <class T, class U>
michael@0 777 inline
michael@0 778 bool
michael@0 779 operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 780 {
michael@0 781 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 782 }
michael@0 783 #endif
michael@0 784
michael@0 785
michael@0 786
michael@0 787 // Comparing an |nsAutoArrayPtr| to |0|
michael@0 788
michael@0 789 template <class T>
michael@0 790 inline
michael@0 791 bool
michael@0 792 operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 793 // specifically to allow |smartPtr == 0|
michael@0 794 {
michael@0 795 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 796 }
michael@0 797
michael@0 798 template <class T>
michael@0 799 inline
michael@0 800 bool
michael@0 801 operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 802 // specifically to allow |0 == smartPtr|
michael@0 803 {
michael@0 804 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 805 }
michael@0 806
michael@0 807 template <class T>
michael@0 808 inline
michael@0 809 bool
michael@0 810 operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 811 // specifically to allow |smartPtr != 0|
michael@0 812 {
michael@0 813 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
michael@0 814 }
michael@0 815
michael@0 816 template <class T>
michael@0 817 inline
michael@0 818 bool
michael@0 819 operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 820 // specifically to allow |0 != smartPtr|
michael@0 821 {
michael@0 822 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
michael@0 823 }
michael@0 824
michael@0 825
michael@0 826 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
michael@0 827
michael@0 828 // We need to explicitly define comparison operators for `int'
michael@0 829 // because the compiler is lame.
michael@0 830
michael@0 831 template <class T>
michael@0 832 inline
michael@0 833 bool
michael@0 834 operator==( const nsAutoArrayPtr<T>& lhs, int rhs )
michael@0 835 // specifically to allow |smartPtr == 0|
michael@0 836 {
michael@0 837 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 838 }
michael@0 839
michael@0 840 template <class T>
michael@0 841 inline
michael@0 842 bool
michael@0 843 operator==( int lhs, const nsAutoArrayPtr<T>& rhs )
michael@0 844 // specifically to allow |0 == smartPtr|
michael@0 845 {
michael@0 846 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 847 }
michael@0 848
michael@0 849 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
michael@0 850
michael@0 851
michael@0 852 /*****************************************************************************/
michael@0 853
michael@0 854 // template <class T> class nsRefPtrGetterAddRefs;
michael@0 855
michael@0 856 template <class T>
michael@0 857 class nsRefPtr
michael@0 858 {
michael@0 859 private:
michael@0 860
michael@0 861 void
michael@0 862 assign_with_AddRef( T* rawPtr )
michael@0 863 {
michael@0 864 if ( rawPtr )
michael@0 865 rawPtr->AddRef();
michael@0 866 assign_assuming_AddRef(rawPtr);
michael@0 867 }
michael@0 868
michael@0 869 void**
michael@0 870 begin_assignment()
michael@0 871 {
michael@0 872 assign_assuming_AddRef(0);
michael@0 873 return reinterpret_cast<void**>(&mRawPtr);
michael@0 874 }
michael@0 875
michael@0 876 void
michael@0 877 assign_assuming_AddRef( T* newPtr )
michael@0 878 {
michael@0 879 T* oldPtr = mRawPtr;
michael@0 880 mRawPtr = newPtr;
michael@0 881 if ( oldPtr )
michael@0 882 oldPtr->Release();
michael@0 883 }
michael@0 884
michael@0 885 private:
michael@0 886 T* mRawPtr;
michael@0 887
michael@0 888 public:
michael@0 889 typedef T element_type;
michael@0 890
michael@0 891 ~nsRefPtr()
michael@0 892 {
michael@0 893 if ( mRawPtr )
michael@0 894 mRawPtr->Release();
michael@0 895 }
michael@0 896
michael@0 897 // Constructors
michael@0 898
michael@0 899 nsRefPtr()
michael@0 900 : mRawPtr(0)
michael@0 901 // default constructor
michael@0 902 {
michael@0 903 }
michael@0 904
michael@0 905 nsRefPtr(const nsRefPtr<T>& aSmartPtr)
michael@0 906 : mRawPtr(aSmartPtr.mRawPtr)
michael@0 907 // copy-constructor
michael@0 908 {
michael@0 909 if ( mRawPtr )
michael@0 910 mRawPtr->AddRef();
michael@0 911 }
michael@0 912
michael@0 913 nsRefPtr(nsRefPtr<T>&& aRefPtr)
michael@0 914 : mRawPtr(aRefPtr.mRawPtr)
michael@0 915 {
michael@0 916 aRefPtr.mRawPtr = nullptr;
michael@0 917 }
michael@0 918
michael@0 919 // construct from a raw pointer (of the right type)
michael@0 920
michael@0 921 nsRefPtr(T* aRawPtr)
michael@0 922 : mRawPtr(aRawPtr)
michael@0 923 {
michael@0 924 if ( mRawPtr )
michael@0 925 mRawPtr->AddRef();
michael@0 926 }
michael@0 927
michael@0 928 template <typename I>
michael@0 929 nsRefPtr( already_AddRefed<I>& aSmartPtr )
michael@0 930 : mRawPtr(aSmartPtr.take())
michael@0 931 // construct from |already_AddRefed|
michael@0 932 {
michael@0 933 }
michael@0 934
michael@0 935 template <typename I>
michael@0 936 nsRefPtr( already_AddRefed<I>&& aSmartPtr )
michael@0 937 : mRawPtr(aSmartPtr.take())
michael@0 938 // construct from |otherRefPtr.forget()|
michael@0 939 {
michael@0 940 }
michael@0 941
michael@0 942 nsRefPtr( const nsCOMPtr_helper& helper )
michael@0 943 {
michael@0 944 void* newRawPtr;
michael@0 945 if (NS_FAILED(helper(NS_GET_TEMPLATE_IID(T), &newRawPtr)))
michael@0 946 newRawPtr = 0;
michael@0 947 mRawPtr = static_cast<T*>(newRawPtr);
michael@0 948 }
michael@0 949
michael@0 950 // Assignment operators
michael@0 951
michael@0 952 nsRefPtr<T>&
michael@0 953 operator=(const nsRefPtr<T>& rhs)
michael@0 954 // copy assignment operator
michael@0 955 {
michael@0 956 assign_with_AddRef(rhs.mRawPtr);
michael@0 957 return *this;
michael@0 958 }
michael@0 959
michael@0 960 nsRefPtr<T>&
michael@0 961 operator=( T* rhs )
michael@0 962 // assign from a raw pointer (of the right type)
michael@0 963 {
michael@0 964 assign_with_AddRef(rhs);
michael@0 965 return *this;
michael@0 966 }
michael@0 967
michael@0 968 template <typename I>
michael@0 969 nsRefPtr<T>&
michael@0 970 operator=( already_AddRefed<I>& rhs )
michael@0 971 // assign from |already_AddRefed|
michael@0 972 {
michael@0 973 assign_assuming_AddRef(rhs.take());
michael@0 974 return *this;
michael@0 975 }
michael@0 976
michael@0 977 template <typename I>
michael@0 978 nsRefPtr<T>&
michael@0 979 operator=( already_AddRefed<I>&& rhs )
michael@0 980 // assign from |otherRefPtr.forget()|
michael@0 981 {
michael@0 982 assign_assuming_AddRef(rhs.take());
michael@0 983 return *this;
michael@0 984 }
michael@0 985
michael@0 986 nsRefPtr<T>&
michael@0 987 operator=( const nsCOMPtr_helper& helper )
michael@0 988 {
michael@0 989 void* newRawPtr;
michael@0 990 if (NS_FAILED(helper(NS_GET_TEMPLATE_IID(T), &newRawPtr)))
michael@0 991 newRawPtr = 0;
michael@0 992 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
michael@0 993 return *this;
michael@0 994 }
michael@0 995
michael@0 996 nsRefPtr<T>&
michael@0 997 operator=(nsRefPtr<T>&& aRefPtr)
michael@0 998 {
michael@0 999 assign_assuming_AddRef(aRefPtr.mRawPtr);
michael@0 1000 aRefPtr.mRawPtr = nullptr;
michael@0 1001 return *this;
michael@0 1002 }
michael@0 1003
michael@0 1004 // Other pointer operators
michael@0 1005
michael@0 1006 void
michael@0 1007 swap( nsRefPtr<T>& rhs )
michael@0 1008 // ...exchange ownership with |rhs|; can save a pair of refcount operations
michael@0 1009 {
michael@0 1010 T* temp = rhs.mRawPtr;
michael@0 1011 rhs.mRawPtr = mRawPtr;
michael@0 1012 mRawPtr = temp;
michael@0 1013 }
michael@0 1014
michael@0 1015 void
michael@0 1016 swap( T*& rhs )
michael@0 1017 // ...exchange ownership with |rhs|; can save a pair of refcount operations
michael@0 1018 {
michael@0 1019 T* temp = rhs;
michael@0 1020 rhs = mRawPtr;
michael@0 1021 mRawPtr = temp;
michael@0 1022 }
michael@0 1023
michael@0 1024 already_AddRefed<T>
michael@0 1025 forget()
michael@0 1026 // return the value of mRawPtr and null out mRawPtr. Useful for
michael@0 1027 // already_AddRefed return values.
michael@0 1028 {
michael@0 1029 T* temp = 0;
michael@0 1030 swap(temp);
michael@0 1031 return already_AddRefed<T>(temp);
michael@0 1032 }
michael@0 1033
michael@0 1034 template <typename I>
michael@0 1035 void
michael@0 1036 forget( I** rhs)
michael@0 1037 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
michael@0 1038 // Useful to avoid unnecessary AddRef/Release pairs with "out"
michael@0 1039 // parameters where rhs bay be a T** or an I** where I is a base class
michael@0 1040 // of T.
michael@0 1041 {
michael@0 1042 NS_ASSERTION(rhs, "Null pointer passed to forget!");
michael@0 1043 *rhs = mRawPtr;
michael@0 1044 mRawPtr = 0;
michael@0 1045 }
michael@0 1046
michael@0 1047 T*
michael@0 1048 get() const
michael@0 1049 /*
michael@0 1050 Prefer the implicit conversion provided automatically by |operator T*() const|.
michael@0 1051 Use |get()| to resolve ambiguity or to get a castable pointer.
michael@0 1052 */
michael@0 1053 {
michael@0 1054 return const_cast<T*>(mRawPtr);
michael@0 1055 }
michael@0 1056
michael@0 1057 operator T*() const
michael@0 1058 /*
michael@0 1059 ...makes an |nsRefPtr| act like its underlying raw pointer type whenever it
michael@0 1060 is used in a context where a raw pointer is expected. It is this operator
michael@0 1061 that makes an |nsRefPtr| substitutable for a raw pointer.
michael@0 1062
michael@0 1063 Prefer the implicit use of this operator to calling |get()|, except where
michael@0 1064 necessary to resolve ambiguity.
michael@0 1065 */
michael@0 1066 {
michael@0 1067 return get();
michael@0 1068 }
michael@0 1069
michael@0 1070 T*
michael@0 1071 operator->() const
michael@0 1072 {
michael@0 1073 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
michael@0 1074 return get();
michael@0 1075 }
michael@0 1076
michael@0 1077 // This operator is needed for gcc <= 4.0.* and for Sun Studio; it
michael@0 1078 // causes internal compiler errors for some MSVC versions. (It's not
michael@0 1079 // clear to me whether it should be needed.)
michael@0 1080 #ifndef _MSC_VER
michael@0 1081 template <class U, class V>
michael@0 1082 U&
michael@0 1083 operator->*(U V::* aMember)
michael@0 1084 {
michael@0 1085 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->*().");
michael@0 1086 return get()->*aMember;
michael@0 1087 }
michael@0 1088 #endif
michael@0 1089
michael@0 1090 nsRefPtr<T>*
michael@0 1091 get_address()
michael@0 1092 // This is not intended to be used by clients. See |address_of|
michael@0 1093 // below.
michael@0 1094 {
michael@0 1095 return this;
michael@0 1096 }
michael@0 1097
michael@0 1098 const nsRefPtr<T>*
michael@0 1099 get_address() const
michael@0 1100 // This is not intended to be used by clients. See |address_of|
michael@0 1101 // below.
michael@0 1102 {
michael@0 1103 return this;
michael@0 1104 }
michael@0 1105
michael@0 1106 public:
michael@0 1107 T&
michael@0 1108 operator*() const
michael@0 1109 {
michael@0 1110 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*().");
michael@0 1111 return *get();
michael@0 1112 }
michael@0 1113
michael@0 1114 T**
michael@0 1115 StartAssignment()
michael@0 1116 {
michael@0 1117 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
michael@0 1118 return reinterpret_cast<T**>(begin_assignment());
michael@0 1119 #else
michael@0 1120 assign_assuming_AddRef(0);
michael@0 1121 return reinterpret_cast<T**>(&mRawPtr);
michael@0 1122 #endif
michael@0 1123 }
michael@0 1124 };
michael@0 1125
michael@0 1126 template <typename T>
michael@0 1127 inline void
michael@0 1128 ImplCycleCollectionUnlink(nsRefPtr<T>& aField)
michael@0 1129 {
michael@0 1130 aField = nullptr;
michael@0 1131 }
michael@0 1132
michael@0 1133 template <typename T>
michael@0 1134 inline void
michael@0 1135 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
michael@0 1136 nsRefPtr<T>& aField,
michael@0 1137 const char* aName,
michael@0 1138 uint32_t aFlags = 0)
michael@0 1139 {
michael@0 1140 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
michael@0 1141 }
michael@0 1142
michael@0 1143 template <class T>
michael@0 1144 inline
michael@0 1145 nsRefPtr<T>*
michael@0 1146 address_of( nsRefPtr<T>& aPtr )
michael@0 1147 {
michael@0 1148 return aPtr.get_address();
michael@0 1149 }
michael@0 1150
michael@0 1151 template <class T>
michael@0 1152 inline
michael@0 1153 const nsRefPtr<T>*
michael@0 1154 address_of( const nsRefPtr<T>& aPtr )
michael@0 1155 {
michael@0 1156 return aPtr.get_address();
michael@0 1157 }
michael@0 1158
michael@0 1159 template <class T>
michael@0 1160 class nsRefPtrGetterAddRefs
michael@0 1161 /*
michael@0 1162 ...
michael@0 1163
michael@0 1164 This class is designed to be used for anonymous temporary objects in the
michael@0 1165 argument list of calls that return COM interface pointers, e.g.,
michael@0 1166
michael@0 1167 nsRefPtr<IFoo> fooP;
michael@0 1168 ...->GetAddRefedPointer(getter_AddRefs(fooP))
michael@0 1169
michael@0 1170 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
michael@0 1171
michael@0 1172 When initialized with a |nsRefPtr|, as in the example above, it returns
michael@0 1173 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
michael@0 1174 outer call (|GetAddRefedPointer| in this case) can fill in.
michael@0 1175
michael@0 1176 This type should be a nested class inside |nsRefPtr<T>|.
michael@0 1177 */
michael@0 1178 {
michael@0 1179 public:
michael@0 1180 explicit
michael@0 1181 nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr )
michael@0 1182 : mTargetSmartPtr(aSmartPtr)
michael@0 1183 {
michael@0 1184 // nothing else to do
michael@0 1185 }
michael@0 1186
michael@0 1187 operator void**()
michael@0 1188 {
michael@0 1189 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
michael@0 1190 }
michael@0 1191
michael@0 1192 operator T**()
michael@0 1193 {
michael@0 1194 return mTargetSmartPtr.StartAssignment();
michael@0 1195 }
michael@0 1196
michael@0 1197 T*&
michael@0 1198 operator*()
michael@0 1199 {
michael@0 1200 return *(mTargetSmartPtr.StartAssignment());
michael@0 1201 }
michael@0 1202
michael@0 1203 private:
michael@0 1204 nsRefPtr<T>& mTargetSmartPtr;
michael@0 1205 };
michael@0 1206
michael@0 1207 template <class T>
michael@0 1208 inline
michael@0 1209 nsRefPtrGetterAddRefs<T>
michael@0 1210 getter_AddRefs( nsRefPtr<T>& aSmartPtr )
michael@0 1211 /*
michael@0 1212 Used around a |nsRefPtr| when
michael@0 1213 ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
michael@0 1214 */
michael@0 1215 {
michael@0 1216 return nsRefPtrGetterAddRefs<T>(aSmartPtr);
michael@0 1217 }
michael@0 1218
michael@0 1219
michael@0 1220
michael@0 1221 // Comparing two |nsRefPtr|s
michael@0 1222
michael@0 1223 template <class T, class U>
michael@0 1224 inline
michael@0 1225 bool
michael@0 1226 operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
michael@0 1227 {
michael@0 1228 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
michael@0 1229 }
michael@0 1230
michael@0 1231
michael@0 1232 template <class T, class U>
michael@0 1233 inline
michael@0 1234 bool
michael@0 1235 operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
michael@0 1236 {
michael@0 1237 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
michael@0 1238 }
michael@0 1239
michael@0 1240
michael@0 1241 // Comparing an |nsRefPtr| to a raw pointer
michael@0 1242
michael@0 1243 template <class T, class U>
michael@0 1244 inline
michael@0 1245 bool
michael@0 1246 operator==( const nsRefPtr<T>& lhs, const U* rhs )
michael@0 1247 {
michael@0 1248 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
michael@0 1249 }
michael@0 1250
michael@0 1251 template <class T, class U>
michael@0 1252 inline
michael@0 1253 bool
michael@0 1254 operator==( const U* lhs, const nsRefPtr<T>& rhs )
michael@0 1255 {
michael@0 1256 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 1257 }
michael@0 1258
michael@0 1259 template <class T, class U>
michael@0 1260 inline
michael@0 1261 bool
michael@0 1262 operator!=( const nsRefPtr<T>& lhs, const U* rhs )
michael@0 1263 {
michael@0 1264 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
michael@0 1265 }
michael@0 1266
michael@0 1267 template <class T, class U>
michael@0 1268 inline
michael@0 1269 bool
michael@0 1270 operator!=( const U* lhs, const nsRefPtr<T>& rhs )
michael@0 1271 {
michael@0 1272 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 1273 }
michael@0 1274
michael@0 1275 // To avoid ambiguities caused by the presence of builtin |operator==|s
michael@0 1276 // creating a situation where one of the |operator==| defined above
michael@0 1277 // has a better conversion for one argument and the builtin has a
michael@0 1278 // better conversion for the other argument, define additional
michael@0 1279 // |operator==| without the |const| on the raw pointer.
michael@0 1280 // See bug 65664 for details.
michael@0 1281
michael@0 1282 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
michael@0 1283 template <class T, class U>
michael@0 1284 inline
michael@0 1285 bool
michael@0 1286 operator==( const nsRefPtr<T>& lhs, U* rhs )
michael@0 1287 {
michael@0 1288 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
michael@0 1289 }
michael@0 1290
michael@0 1291 template <class T, class U>
michael@0 1292 inline
michael@0 1293 bool
michael@0 1294 operator==( U* lhs, const nsRefPtr<T>& rhs )
michael@0 1295 {
michael@0 1296 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
michael@0 1297 }
michael@0 1298
michael@0 1299 template <class T, class U>
michael@0 1300 inline
michael@0 1301 bool
michael@0 1302 operator!=( const nsRefPtr<T>& lhs, U* rhs )
michael@0 1303 {
michael@0 1304 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
michael@0 1305 }
michael@0 1306
michael@0 1307 template <class T, class U>
michael@0 1308 inline
michael@0 1309 bool
michael@0 1310 operator!=( U* lhs, const nsRefPtr<T>& rhs )
michael@0 1311 {
michael@0 1312 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
michael@0 1313 }
michael@0 1314 #endif
michael@0 1315
michael@0 1316
michael@0 1317
michael@0 1318 // Comparing an |nsRefPtr| to |0|
michael@0 1319
michael@0 1320 template <class T>
michael@0 1321 inline
michael@0 1322 bool
michael@0 1323 operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 1324 // specifically to allow |smartPtr == 0|
michael@0 1325 {
michael@0 1326 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 1327 }
michael@0 1328
michael@0 1329 template <class T>
michael@0 1330 inline
michael@0 1331 bool
michael@0 1332 operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
michael@0 1333 // specifically to allow |0 == smartPtr|
michael@0 1334 {
michael@0 1335 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 1336 }
michael@0 1337
michael@0 1338 template <class T>
michael@0 1339 inline
michael@0 1340 bool
michael@0 1341 operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
michael@0 1342 // specifically to allow |smartPtr != 0|
michael@0 1343 {
michael@0 1344 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
michael@0 1345 }
michael@0 1346
michael@0 1347 template <class T>
michael@0 1348 inline
michael@0 1349 bool
michael@0 1350 operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
michael@0 1351 // specifically to allow |0 != smartPtr|
michael@0 1352 {
michael@0 1353 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
michael@0 1354 }
michael@0 1355
michael@0 1356
michael@0 1357 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
michael@0 1358
michael@0 1359 // We need to explicitly define comparison operators for `int'
michael@0 1360 // because the compiler is lame.
michael@0 1361
michael@0 1362 template <class T>
michael@0 1363 inline
michael@0 1364 bool
michael@0 1365 operator==( const nsRefPtr<T>& lhs, int rhs )
michael@0 1366 // specifically to allow |smartPtr == 0|
michael@0 1367 {
michael@0 1368 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
michael@0 1369 }
michael@0 1370
michael@0 1371 template <class T>
michael@0 1372 inline
michael@0 1373 bool
michael@0 1374 operator==( int lhs, const nsRefPtr<T>& rhs )
michael@0 1375 // specifically to allow |0 == smartPtr|
michael@0 1376 {
michael@0 1377 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
michael@0 1378 }
michael@0 1379
michael@0 1380 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
michael@0 1381
michael@0 1382 template <class SourceType, class DestinationType>
michael@0 1383 inline
michael@0 1384 nsresult
michael@0 1385 CallQueryInterface( nsRefPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
michael@0 1386 {
michael@0 1387 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
michael@0 1388 }
michael@0 1389
michael@0 1390 /*****************************************************************************/
michael@0 1391
michael@0 1392 template<class T>
michael@0 1393 class nsQueryObject : public nsCOMPtr_helper
michael@0 1394 {
michael@0 1395 public:
michael@0 1396 nsQueryObject(T* aRawPtr)
michael@0 1397 : mRawPtr(aRawPtr) {}
michael@0 1398
michael@0 1399 virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aResult ) const {
michael@0 1400 nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult)
michael@0 1401 : NS_ERROR_NULL_POINTER;
michael@0 1402 return status;
michael@0 1403 }
michael@0 1404 private:
michael@0 1405 T* mRawPtr;
michael@0 1406 };
michael@0 1407
michael@0 1408 template<class T>
michael@0 1409 class nsQueryObjectWithError : public nsCOMPtr_helper
michael@0 1410 {
michael@0 1411 public:
michael@0 1412 nsQueryObjectWithError(T* aRawPtr, nsresult* aErrorPtr)
michael@0 1413 : mRawPtr(aRawPtr), mErrorPtr(aErrorPtr) {}
michael@0 1414
michael@0 1415 virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aResult ) const {
michael@0 1416 nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult)
michael@0 1417 : NS_ERROR_NULL_POINTER;
michael@0 1418 if (mErrorPtr)
michael@0 1419 *mErrorPtr = status;
michael@0 1420 return status;
michael@0 1421 }
michael@0 1422 private:
michael@0 1423 T* mRawPtr;
michael@0 1424 nsresult* mErrorPtr;
michael@0 1425 };
michael@0 1426
michael@0 1427 template<class T>
michael@0 1428 inline
michael@0 1429 nsQueryObject<T>
michael@0 1430 do_QueryObject(T* aRawPtr)
michael@0 1431 {
michael@0 1432 return nsQueryObject<T>(aRawPtr);
michael@0 1433 }
michael@0 1434
michael@0 1435 template<class T>
michael@0 1436 inline
michael@0 1437 nsQueryObject<T>
michael@0 1438 do_QueryObject(nsCOMPtr<T>& aRawPtr)
michael@0 1439 {
michael@0 1440 return nsQueryObject<T>(aRawPtr);
michael@0 1441 }
michael@0 1442
michael@0 1443 template<class T>
michael@0 1444 inline
michael@0 1445 nsQueryObject<T>
michael@0 1446 do_QueryObject(nsRefPtr<T>& aRawPtr)
michael@0 1447 {
michael@0 1448 return nsQueryObject<T>(aRawPtr);
michael@0 1449 }
michael@0 1450
michael@0 1451 template<class T>
michael@0 1452 inline
michael@0 1453 nsQueryObjectWithError<T>
michael@0 1454 do_QueryObject(T* aRawPtr, nsresult* aErrorPtr)
michael@0 1455 {
michael@0 1456 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
michael@0 1457 }
michael@0 1458
michael@0 1459 template<class T>
michael@0 1460 inline
michael@0 1461 nsQueryObjectWithError<T>
michael@0 1462 do_QueryObject(nsCOMPtr<T>& aRawPtr, nsresult* aErrorPtr)
michael@0 1463 {
michael@0 1464 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
michael@0 1465 }
michael@0 1466
michael@0 1467 template<class T>
michael@0 1468 inline
michael@0 1469 nsQueryObjectWithError<T>
michael@0 1470 do_QueryObject(nsRefPtr<T>& aRawPtr, nsresult* aErrorPtr)
michael@0 1471 {
michael@0 1472 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
michael@0 1473 }
michael@0 1474
michael@0 1475 /*****************************************************************************/
michael@0 1476
michael@0 1477 #endif // !defined(nsAutoPtr_h___)

mercurial