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