xpcom/base/nsAutoPtr.h

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

mercurial