Sat, 03 Jan 2015 20:18:00 +0100
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.
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/. */
6 #ifndef nsAutoPtr_h___
7 #define nsAutoPtr_h___
9 #include "nsCOMPtr.h"
11 #include "nsCycleCollectionNoteChild.h"
12 #include "mozilla/MemoryReporting.h"
14 /*****************************************************************************/
16 // template <class T> class nsAutoPtrGetterTransfers;
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 }
29 void
30 assign( T* newPtr )
31 {
32 T* oldPtr = mRawPtr;
34 if (newPtr != nullptr && newPtr == oldPtr) {
35 NS_RUNTIMEABORT("Logic flaw in the caller");
36 }
38 mRawPtr = newPtr;
39 delete oldPtr;
40 }
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 }
55 operator T*() const
56 {
57 return mPtr;
58 }
60 private:
61 T* mPtr;
62 };
64 private:
65 T* mRawPtr;
67 public:
68 typedef T element_type;
70 ~nsAutoPtr()
71 {
72 delete mRawPtr;
73 }
75 // Constructors
77 nsAutoPtr()
78 : mRawPtr(0)
79 // default constructor
80 {
81 }
83 nsAutoPtr( Ptr aRawPtr )
84 : mRawPtr(aRawPtr)
85 // construct from a raw pointer (of the right type)
86 {
87 }
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 }
97 nsAutoPtr( nsAutoPtr<T>&& aSmartPtr )
98 : mRawPtr( aSmartPtr.forget() )
99 // Construct by transferring ownership from another smart pointer.
100 {
101 }
103 // Assignment operators
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 }
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 }
120 // Other pointer operators
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 }
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.
140 Prefer the implicit use of this operator to calling |get()|,
141 except where necessary to resolve ambiguity.
142 */
143 {
144 return get();
145 }
147 T*
148 forget()
149 {
150 T* temp = mRawPtr;
151 mRawPtr = 0;
152 return temp;
153 }
155 T*
156 operator->() const
157 {
158 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
159 return get();
160 }
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
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 }
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 }
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 }
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 };
211 template <class T>
212 inline
213 nsAutoPtr<T>*
214 address_of( nsAutoPtr<T>& aPtr )
215 {
216 return aPtr.get_address();
217 }
219 template <class T>
220 inline
221 const nsAutoPtr<T>*
222 address_of( const nsAutoPtr<T>& aPtr )
223 {
224 return aPtr.get_address();
225 }
227 template <class T>
228 class nsAutoPtrGetterTransfers
229 /*
230 ...
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.,
235 nsAutoPtr<IFoo> fooP;
236 ...->GetTransferedPointer(getter_Transfers(fooP))
238 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
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.
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 }
255 operator void**()
256 {
257 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
258 }
260 operator T**()
261 {
262 return mTargetSmartPtr.StartAssignment();
263 }
265 T*&
266 operator*()
267 {
268 return *(mTargetSmartPtr.StartAssignment());
269 }
271 private:
272 nsAutoPtr<T>& mTargetSmartPtr;
273 };
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 }
289 // Comparing two |nsAutoPtr|s
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 }
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 }
309 // Comparing an |nsAutoPtr| to a raw pointer
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 }
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 }
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 }
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 }
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.
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 }
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 }
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 }
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
386 // Comparing an |nsAutoPtr| to |0|
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 }
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 }
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 }
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 }
425 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
427 // We need to explicitly define comparison operators for `int'
428 // because the compiler is lame.
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 }
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 }
448 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
450 /*****************************************************************************/
452 // template <class T> class nsAutoArrayPtrGetterTransfers;
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 }
465 void
466 assign( T* newPtr )
467 {
468 T* oldPtr = mRawPtr;
469 mRawPtr = newPtr;
470 delete [] oldPtr;
471 }
473 private:
474 T* mRawPtr;
476 public:
477 typedef T element_type;
479 ~nsAutoArrayPtr()
480 {
481 delete [] mRawPtr;
482 }
484 // Constructors
486 nsAutoArrayPtr()
487 : mRawPtr(0)
488 // default constructor
489 {
490 }
492 nsAutoArrayPtr( T* aRawPtr )
493 : mRawPtr(aRawPtr)
494 // construct from a raw pointer (of the right type)
495 {
496 }
498 nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
499 : mRawPtr( aSmartPtr.forget() )
500 // Construct by transferring ownership from another smart pointer.
501 {
502 }
505 // Assignment operators
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 }
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 }
522 // Other pointer operators
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 }
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.
542 Prefer the implicit use of this operator to calling |get()|,
543 except where necessary to resolve ambiguity.
544 */
545 {
546 return get();
547 }
549 T*
550 forget()
551 {
552 T* temp = mRawPtr;
553 mRawPtr = 0;
554 return temp;
555 }
557 T*
558 operator->() const
559 {
560 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
561 return get();
562 }
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 }
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 }
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 }
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 }
599 size_t
600 SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
601 {
602 return aMallocSizeOf(mRawPtr);
603 }
605 size_t
606 SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
607 {
608 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
609 }
610 };
612 template <class T>
613 inline
614 nsAutoArrayPtr<T>*
615 address_of( nsAutoArrayPtr<T>& aPtr )
616 {
617 return aPtr.get_address();
618 }
620 template <class T>
621 inline
622 const nsAutoArrayPtr<T>*
623 address_of( const nsAutoArrayPtr<T>& aPtr )
624 {
625 return aPtr.get_address();
626 }
628 template <class T>
629 class nsAutoArrayPtrGetterTransfers
630 /*
631 ...
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.,
636 nsAutoArrayPtr<IFoo> fooP;
637 ...->GetTransferedPointer(getter_Transfers(fooP))
639 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
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.
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 }
656 operator void**()
657 {
658 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
659 }
661 operator T**()
662 {
663 return mTargetSmartPtr.StartAssignment();
664 }
666 T*&
667 operator*()
668 {
669 return *(mTargetSmartPtr.StartAssignment());
670 }
672 private:
673 nsAutoArrayPtr<T>& mTargetSmartPtr;
674 };
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 }
690 // Comparing two |nsAutoArrayPtr|s
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 }
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 }
710 // Comparing an |nsAutoArrayPtr| to a raw pointer
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 }
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 }
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 }
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 }
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.
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 }
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 }
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 }
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
787 // Comparing an |nsAutoArrayPtr| to |0|
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 }
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 }
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 }
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 }
826 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
828 // We need to explicitly define comparison operators for `int'
829 // because the compiler is lame.
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 }
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 }
849 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
852 /*****************************************************************************/
854 // template <class T> class nsRefPtrGetterAddRefs;
856 template <class T>
857 class nsRefPtr
858 {
859 private:
861 void
862 assign_with_AddRef( T* rawPtr )
863 {
864 if ( rawPtr )
865 rawPtr->AddRef();
866 assign_assuming_AddRef(rawPtr);
867 }
869 void**
870 begin_assignment()
871 {
872 assign_assuming_AddRef(0);
873 return reinterpret_cast<void**>(&mRawPtr);
874 }
876 void
877 assign_assuming_AddRef( T* newPtr )
878 {
879 T* oldPtr = mRawPtr;
880 mRawPtr = newPtr;
881 if ( oldPtr )
882 oldPtr->Release();
883 }
885 private:
886 T* mRawPtr;
888 public:
889 typedef T element_type;
891 ~nsRefPtr()
892 {
893 if ( mRawPtr )
894 mRawPtr->Release();
895 }
897 // Constructors
899 nsRefPtr()
900 : mRawPtr(0)
901 // default constructor
902 {
903 }
905 nsRefPtr(const nsRefPtr<T>& aSmartPtr)
906 : mRawPtr(aSmartPtr.mRawPtr)
907 // copy-constructor
908 {
909 if ( mRawPtr )
910 mRawPtr->AddRef();
911 }
913 nsRefPtr(nsRefPtr<T>&& aRefPtr)
914 : mRawPtr(aRefPtr.mRawPtr)
915 {
916 aRefPtr.mRawPtr = nullptr;
917 }
919 // construct from a raw pointer (of the right type)
921 nsRefPtr(T* aRawPtr)
922 : mRawPtr(aRawPtr)
923 {
924 if ( mRawPtr )
925 mRawPtr->AddRef();
926 }
928 template <typename I>
929 nsRefPtr( already_AddRefed<I>& aSmartPtr )
930 : mRawPtr(aSmartPtr.take())
931 // construct from |already_AddRefed|
932 {
933 }
935 template <typename I>
936 nsRefPtr( already_AddRefed<I>&& aSmartPtr )
937 : mRawPtr(aSmartPtr.take())
938 // construct from |otherRefPtr.forget()|
939 {
940 }
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 }
950 // Assignment operators
952 nsRefPtr<T>&
953 operator=(const nsRefPtr<T>& rhs)
954 // copy assignment operator
955 {
956 assign_with_AddRef(rhs.mRawPtr);
957 return *this;
958 }
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 }
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 }
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 }
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 }
996 nsRefPtr<T>&
997 operator=(nsRefPtr<T>&& aRefPtr)
998 {
999 assign_assuming_AddRef(aRefPtr.mRawPtr);
1000 aRefPtr.mRawPtr = nullptr;
1001 return *this;
1002 }
1004 // Other pointer operators
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 }
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 }
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 }
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 }
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 }
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.
1063 Prefer the implicit use of this operator to calling |get()|, except where
1064 necessary to resolve ambiguity.
1065 */
1066 {
1067 return get();
1068 }
1070 T*
1071 operator->() const
1072 {
1073 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
1074 return get();
1075 }
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
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 }
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 }
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 }
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 };
1126 template <typename T>
1127 inline void
1128 ImplCycleCollectionUnlink(nsRefPtr<T>& aField)
1129 {
1130 aField = nullptr;
1131 }
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 }
1143 template <class T>
1144 inline
1145 nsRefPtr<T>*
1146 address_of( nsRefPtr<T>& aPtr )
1147 {
1148 return aPtr.get_address();
1149 }
1151 template <class T>
1152 inline
1153 const nsRefPtr<T>*
1154 address_of( const nsRefPtr<T>& aPtr )
1155 {
1156 return aPtr.get_address();
1157 }
1159 template <class T>
1160 class nsRefPtrGetterAddRefs
1161 /*
1162 ...
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.,
1167 nsRefPtr<IFoo> fooP;
1168 ...->GetAddRefedPointer(getter_AddRefs(fooP))
1170 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
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.
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 }
1187 operator void**()
1188 {
1189 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1190 }
1192 operator T**()
1193 {
1194 return mTargetSmartPtr.StartAssignment();
1195 }
1197 T*&
1198 operator*()
1199 {
1200 return *(mTargetSmartPtr.StartAssignment());
1201 }
1203 private:
1204 nsRefPtr<T>& mTargetSmartPtr;
1205 };
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 }
1221 // Comparing two |nsRefPtr|s
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 }
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 }
1241 // Comparing an |nsRefPtr| to a raw pointer
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 }
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 }
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 }
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 }
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.
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 }
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 }
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 }
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
1318 // Comparing an |nsRefPtr| to |0|
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 }
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 }
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 }
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 }
1357 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1359 // We need to explicitly define comparison operators for `int'
1360 // because the compiler is lame.
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 }
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 }
1380 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
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 }
1390 /*****************************************************************************/
1392 template<class T>
1393 class nsQueryObject : public nsCOMPtr_helper
1394 {
1395 public:
1396 nsQueryObject(T* aRawPtr)
1397 : mRawPtr(aRawPtr) {}
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 };
1408 template<class T>
1409 class nsQueryObjectWithError : public nsCOMPtr_helper
1410 {
1411 public:
1412 nsQueryObjectWithError(T* aRawPtr, nsresult* aErrorPtr)
1413 : mRawPtr(aRawPtr), mErrorPtr(aErrorPtr) {}
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 };
1427 template<class T>
1428 inline
1429 nsQueryObject<T>
1430 do_QueryObject(T* aRawPtr)
1431 {
1432 return nsQueryObject<T>(aRawPtr);
1433 }
1435 template<class T>
1436 inline
1437 nsQueryObject<T>
1438 do_QueryObject(nsCOMPtr<T>& aRawPtr)
1439 {
1440 return nsQueryObject<T>(aRawPtr);
1441 }
1443 template<class T>
1444 inline
1445 nsQueryObject<T>
1446 do_QueryObject(nsRefPtr<T>& aRawPtr)
1447 {
1448 return nsQueryObject<T>(aRawPtr);
1449 }
1451 template<class T>
1452 inline
1453 nsQueryObjectWithError<T>
1454 do_QueryObject(T* aRawPtr, nsresult* aErrorPtr)
1455 {
1456 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
1457 }
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 }
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 }
1475 /*****************************************************************************/
1477 #endif // !defined(nsAutoPtr_h___)