VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h@ 78394

Last change on this file since 78394 was 1, checked in by vboxsync, 55 years ago

import

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette