source: trunk/third/firefox/xpcom/base/nsAutoPtr.h @ 21695

Revision 21695, 32.7 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
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 <scc@mozilla.org> (original author of nsCOMPtr)
24 *   L. David Baron <dbaron@dbaron.org>
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * 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 NPL, 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 NPL, 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.