Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: gecko-sdk/include/nsCOMPtr.h

Issue 20346: Version 1.8 of gecko-sdk. Downloaded from here:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gecko-sdk/include/nsBuildID.h ('k') | gecko-sdk/include/nsComponentManagerUtils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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)
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 nsCOMPtr_h___
41 #define nsCOMPtr_h___
42
43 /*
44 Having problems?
45
46 See the User Manual at:
47 http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
48
49
50 nsCOMPtr
51 better than a raw pointer
52 for owning objects
53 -- scc
54 */
55
56
57 // Wrapping includes can speed up compiles (see "Large Scale C++ Software Desi gn")
58 #ifndef nsDebug_h___
59 #include "nsDebug.h"
60 // for |NS_PRECONDITION|
61 #endif
62
63 #ifndef nsISupportsUtils_h__
64 #include "nsISupportsUtils.h"
65 // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
66 #endif
67
68 #ifndef nscore_h___
69 #include "nscore.h"
70 // for |NS_..._CAST|, |NS_COM_GLUE|
71 #endif
72
73
74 /*
75 WARNING:
76 This file defines several macros for internal use only. These macros begin with the
77 prefix |NSCAP_|. Do not use these macros in your own code. They are for in ternal use
78 only for cross-platform compatibility, and are subject to change without not ice.
79 */
80
81
82 #ifdef _MSC_VER
83 #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
84 // under VC++, we win by inlining StartAssignment
85
86 // Also under VC++, at the highest warning level, we are overwhelmed with w arnings
87 // about (unused) inline functions being removed. This is to be expected w ith
88 // templates, so we disable the warning.
89 #pragma warning( disable: 4514 )
90 #endif
91
92 #define NSCAP_FEATURE_USE_BASE
93
94 #ifdef NS_DEBUG
95 #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
96 #undef NSCAP_FEATURE_USE_BASE
97 //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
98 #endif
99
100 /*
101 |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
102 problematic on a select few of our platforms, e.g., QNX. Therefore, I'm pro viding
103 a mechanism by which these features can be explicitly disabled from the comm and-line.
104 */
105
106 #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
107 #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
108 #endif
109
110 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
111 // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
112 // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
113 // don't reorder instructions based on aliasing assumptions for
114 // this variable. Fortunately, gcc versions < 3.3 do not do any
115 // optimizations that break nsCOMPtr.
116
117 #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
118 #else
119 #define NS_MAY_ALIAS_PTR(t) t*
120 #endif
121
122 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
123 #define NSCAP_FEATURE_USE_BASE
124 #endif
125
126
127 #ifdef HAVE_CPP_BOOL
128 typedef bool NSCAP_BOOL;
129 #else
130 typedef PRBool NSCAP_BOOL;
131 #endif
132
133
134
135
136 /*
137 The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ ASSIGNMENT|)
138 allow external clients the ability to add logging or other interesting deb ug facilities.
139 In fact, if you want |nsCOMPtr| to participate in the standard logging fac ility, you
140 provide (e.g., in "nsTraceRefcnt.h") suitable definitions
141
142 #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
143 #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
144 */
145
146 #ifndef NSCAP_ADDREF
147 #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
148 #endif
149
150 #ifndef NSCAP_RELEASE
151 #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
152 #endif
153
154 // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
155 #ifdef NSCAP_LOG_ASSIGNMENT
156 // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that w e know
157 // to instantiate |~nsGetterAddRefs| in turn to note the external assignmen t into
158 // the |nsCOMPtr|.
159 #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
160 #else
161 // ...otherwise, just strip it out of the code
162 #define NSCAP_LOG_ASSIGNMENT(this, ptr)
163 #endif
164
165 #ifndef NSCAP_LOG_RELEASE
166 #define NSCAP_LOG_RELEASE(this, ptr)
167 #endif
168
169
170
171
172 /*
173 WARNING:
174 VC++4.2 is very picky. To compile under VC++4.2, the classes must be defi ned
175 in an order that satisfies:
176
177 nsDerivedSafe < nsCOMPtr
178 already_AddRefed < nsCOMPtr
179 nsCOMPtr < nsGetterAddRefs
180
181 The other compilers probably won't complain, so please don't reorder these
182 classes, on pain of breaking 4.2 compatibility.
183 */
184
185
186 template <class T>
187 class nsDerivedSafe : public T
188 /*
189 No client should ever see or have to type the name of this class. It is t he
190 artifact that makes it a compile-time error to call |AddRef| and |Release|
191 on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
192
193 See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
194
195 This type should be a nested class inside |nsCOMPtr<T>|.
196 */
197 {
198 private:
199 #ifdef HAVE_CPP_ACCESS_CHANGING_USING
200 using T::AddRef;
201 using T::Release;
202 #else
203 nsrefcnt AddRef(void);
204 nsrefcnt Release(void);
205 #endif
206
207 #if !defined(AIX) && !defined(IRIX)
208 void operator delete( void*, size_t ); // NOT TO BE IMPLE MENTED
209 // declaring |operator delete| private makes calling delete on an interf ace pointer a compile error
210 #endif
211
212 nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLE MENTED
213 // you may not call |operator=()| through a dereferenced |nsCOMPtr|, bec ause you'd get the wrong one
214
215 /*
216 Compiler warnings and errors: nsDerivedSafe operator=() hides inherite d operator=().
217 If you see that, that means somebody checked in a [XP]COM interface cl ass that declares an
218 |operator=()|, and that's _bad_. So bad, in fact, that this declarati on exists explicitly
219 to stop people from doing it.
220 */
221
222 protected:
223 nsDerivedSafe(); // NOT TO BE IMPLE MENTED
224 /*
225 This ctor exists to avoid compile errors and warnings about nsDerivied Safe using the
226 default ctor but inheriting classes without an empty ctor. See bug 209 667.
227 */
228 };
229
230 #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMEN TATIONS)
231 template <class T>
232 nsrefcnt
233 nsDerivedSafe<T>::AddRef()
234 {
235 return 0;
236 }
237
238 template <class T>
239 nsrefcnt
240 nsDerivedSafe<T>::Release()
241 {
242 return 0;
243 }
244
245 #endif
246
247
248
249 template <class T>
250 struct already_AddRefed
251 /*
252 ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without _
253 |AddRef|ing it. You might want to use this as a return type from a functi on
254 that produces an already |AddRef|ed pointer as a result.
255
256 See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
257
258 This type should be a nested class inside |nsCOMPtr<T>|.
259
260 Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper | to
261 avoid adding specialized machinery to |nsCOMPtr| ... but this is the simpl est
262 case, and perhaps worth the savings in time and space that its specific
263 implementation affords over the more general solution offered by
264 |nsCOMPtr_helper|.
265 */
266 {
267 already_AddRefed( T* aRawPtr )
268 : mRawPtr(aRawPtr)
269 {
270 // nothing else to do here
271 }
272
273 T* get() const { return mRawPtr; }
274
275 T* mRawPtr;
276 };
277
278 template <class T>
279 inline
280 const already_AddRefed<T>
281 getter_AddRefs( T* aRawPtr )
282 /*
283 ...makes typing easier, because it deduces the template type, e.g.,
284 you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
285 */
286 {
287 return already_AddRefed<T>(aRawPtr);
288 }
289
290 template <class T>
291 inline
292 const already_AddRefed<T>
293 getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
294 {
295 return aAlreadyAddRefedPtr;
296 }
297
298 template <class T>
299 inline
300 const already_AddRefed<T>
301 dont_AddRef( T* aRawPtr )
302 {
303 return already_AddRefed<T>(aRawPtr);
304 }
305
306 template <class T>
307 inline
308 const already_AddRefed<T>
309 dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
310 {
311 return aAlreadyAddRefedPtr;
312 }
313
314
315
316 class nsCOMPtr_helper
317 /*
318 An |nsCOMPtr_helper| transforms commonly called getters into typesafe form s
319 that are more convenient to call, and more efficient to use with |nsCOMPtr |s.
320 Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, et c.
321
322 Here are the rules for a helper:
323 - it implements |operator()| to produce an interface pointer
324 - (except for its name) |operator()| is a valid [XP]COM `getter'
325 - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
326 - it matches the type requested with the supplied |nsIID| argument
327 - its constructor provides an optional |nsresult*| that |operator()| can fill
328 in with an error when it is executed
329
330 See |class nsGetInterface| for an example.
331 */
332 {
333 public:
334 virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
335 };
336
337 /*
338 |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
339 avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
340 is called often enough that the codesize savings are big enough to
341 warrant the specialcasing.
342 */
343
344 class NS_COM_GLUE nsQueryInterface
345 {
346 public:
347 explicit
348 nsQueryInterface( nsISupports* aRawPtr )
349 : mRawPtr(aRawPtr)
350 {
351 // nothing else to do here
352 }
353
354 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
355
356 private:
357 nsISupports* mRawPtr;
358 };
359
360 class NS_COM_GLUE nsQueryInterfaceWithError
361 {
362 public:
363 nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
364 : mRawPtr(aRawPtr),
365 mErrorPtr(error)
366 {
367 // nothing else to do here
368 }
369
370 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
371
372 private:
373 nsISupports* mRawPtr;
374 nsresult* mErrorPtr;
375 };
376
377 inline
378 nsQueryInterface
379 do_QueryInterface( nsISupports* aRawPtr )
380 {
381 return nsQueryInterface(aRawPtr);
382 }
383
384 inline
385 nsQueryInterfaceWithError
386 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
387 {
388 return nsQueryInterfaceWithError(aRawPtr, error);
389 }
390
391 template <class T>
392 inline
393 void
394 do_QueryInterface( already_AddRefed<T>& )
395 {
396 // This signature exists soley to _stop_ you from doing the bad thing.
397 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
398 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/sho w_bug.cgi?id=8221>.
399 }
400
401 template <class T>
402 inline
403 void
404 do_QueryInterface( already_AddRefed<T>&, nsresult* )
405 {
406 // This signature exists soley to _stop_ you from doing the bad thing.
407 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
408 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/sho w_bug.cgi?id=8221>.
409 }
410
411
412 ////////////////////////////////////////////////////////////////////////////
413 // Using servicemanager with COMPtrs
414 class NS_COM_GLUE nsGetServiceByCID
415 {
416 public:
417 nsGetServiceByCID(const nsCID& aCID)
418 : mCID(aCID)
419 {
420 // nothing else to do
421 }
422
423 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
424
425 private:
426 const nsCID& mCID;
427 };
428
429 class NS_COM_GLUE nsGetServiceByCIDWithError
430 {
431 public:
432 nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
433 : mCID(aCID),
434 mErrorPtr(aErrorPtr)
435 {
436 // nothing else to do
437 }
438
439 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
440
441 private:
442 const nsCID& mCID;
443 nsresult* mErrorPtr;
444 };
445
446 class NS_COM_GLUE nsGetServiceByContractID
447 {
448 public:
449 nsGetServiceByContractID(const char* aContractID)
450 : mContractID(aContractID)
451 {
452 // nothing else to do
453 }
454
455 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
456
457 private:
458 const char* mContractID;
459 };
460
461 class NS_COM_GLUE nsGetServiceByContractIDWithError
462 {
463 public:
464 nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorP tr)
465 : mContractID(aContractID),
466 mErrorPtr(aErrorPtr)
467 {
468 // nothing else to do
469 }
470
471 nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
472
473 private:
474 const char* mContractID;
475 nsresult* mErrorPtr;
476 };
477
478 class nsCOMPtr_base
479 /*
480 ...factors implementation for all template versions of |nsCOMPtr|.
481
482 This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
483 because unlike the
484
485 Here's the way people normally do things like this
486
487 template <class T> class Foo { ... };
488 template <> class Foo<void*> { ... };
489 template <class T> class Foo<T*> : private Foo<void*> { ... };
490 */
491 {
492 public:
493
494 nsCOMPtr_base( nsISupports* rawPtr = 0 )
495 : mRawPtr(rawPtr)
496 {
497 // nothing else to do here
498 }
499
500 NS_COM_GLUE NS_FASTCALL ~nsCOMPtr_base();
501
502 NS_COM_GLUE void NS_FASTCALL assign_with_AddRef( nsISupports* );
503 NS_COM_GLUE void NS_FASTCALL assign_from_qi( const nsQueryInterface, con st nsIID& );
504 NS_COM_GLUE void NS_FASTCALL assign_from_qi_with_error( const nsQueryInt erfaceWithError&, const nsIID& );
505 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid( const nsGetServiceByCID , const nsIID& );
506 NS_COM_GLUE void NS_FASTCALL assign_from_gs_cid_with_error( const nsGetS erviceByCIDWithError&, const nsIID& );
507 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid( const nsGetServi ceByContractID, const nsIID& );
508 NS_COM_GLUE void NS_FASTCALL assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
509 NS_COM_GLUE void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
510 NS_COM_GLUE void** NS_FASTCALL begin_assignment();
511
512 protected:
513 NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
514
515 void
516 assign_assuming_AddRef( nsISupports* newPtr )
517 {
518 /*
519 |AddRef()|ing the new value (before entering this function) before
520 |Release()|ing the old lets us safely ignore the self-assignment c ase.
521 We must, however, be careful only to |Release()| _after_ doing the
522 assignment, in case the |Release()| leads to our _own_ destruction ,
523 which would, in turn, cause an incorrect second |Release()| of our old
524 pointer. Thank <waterson@netscape.com> for discovering this.
525 */
526 nsISupports* oldPtr = mRawPtr;
527 mRawPtr = newPtr;
528 NSCAP_LOG_ASSIGNMENT(this, newPtr);
529 NSCAP_LOG_RELEASE(this, oldPtr);
530 if ( oldPtr )
531 NSCAP_RELEASE(this, oldPtr);
532 }
533 };
534
535 // template <class T> class nsGetterAddRefs;
536
537 template <class T>
538 class nsCOMPtr
539 #ifdef NSCAP_FEATURE_USE_BASE
540 : private nsCOMPtr_base
541 #endif
542 {
543
544 #ifdef NSCAP_FEATURE_USE_BASE
545 #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
546 #else
547 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
548
549 private:
550 void assign_with_AddRef( nsISupports* );
551 void assign_from_qi( const nsQueryInterface, const nsIID& );
552 void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
553 void assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
554 void assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
555 void assign_from_gs_contractid( const nsGetServiceByContractID, const n sIID& );
556 void assign_from_gs_contractid_with_error( const nsGetServiceByContract IDWithError&, const nsIID& );
557 void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
558 void** begin_assignment();
559
560 void
561 assign_assuming_AddRef( T* newPtr )
562 {
563 T* oldPtr = mRawPtr;
564 mRawPtr = newPtr;
565 NSCAP_LOG_ASSIGNMENT(this, newPtr);
566 NSCAP_LOG_RELEASE(this, oldPtr);
567 if ( oldPtr )
568 NSCAP_RELEASE(this, oldPtr);
569 }
570
571 private:
572 T* mRawPtr;
573 #endif
574
575 public:
576 typedef T element_type;
577
578 #ifndef NSCAP_FEATURE_USE_BASE
579 ~nsCOMPtr()
580 {
581 NSCAP_LOG_RELEASE(this, mRawPtr);
582 if ( mRawPtr )
583 NSCAP_RELEASE(this, mRawPtr);
584 }
585 #endif
586
587 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
588 void
589 Assert_NoQueryNeeded()
590 {
591 if ( mRawPtr )
592 {
593 nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
594 NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed ");
595 }
596 }
597
598 #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
599 #else
600 #define NSCAP_ASSERT_NO_QUERY_NEEDED()
601 #endif
602
603
604 // Constructors
605
606 nsCOMPtr()
607 : NSCAP_CTOR_BASE(0)
608 // default constructor
609 {
610 NSCAP_LOG_ASSIGNMENT(this, 0);
611 }
612
613 nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
614 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
615 // copy-constructor
616 {
617 if ( mRawPtr )
618 NSCAP_ADDREF(this, mRawPtr);
619 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
620 }
621
622 nsCOMPtr( T* aRawPtr )
623 : NSCAP_CTOR_BASE(aRawPtr)
624 // construct from a raw pointer (of the right type)
625 {
626 if ( mRawPtr )
627 NSCAP_ADDREF(this, mRawPtr);
628 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
629 NSCAP_ASSERT_NO_QUERY_NEEDED();
630 }
631
632 nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
633 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
634 // construct from |dont_AddRef(expr)|
635 {
636 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
637 NSCAP_ASSERT_NO_QUERY_NEEDED();
638 }
639
640 nsCOMPtr( const nsQueryInterface qi )
641 : NSCAP_CTOR_BASE(0)
642 // construct from |do_QueryInterface(expr)|
643 {
644 NSCAP_LOG_ASSIGNMENT(this, 0);
645 assign_from_qi(qi, NS_GET_IID(T));
646 }
647
648 nsCOMPtr( const nsQueryInterfaceWithError& qi )
649 : NSCAP_CTOR_BASE(0)
650 // construct from |do_QueryInterface(expr, &rv)|
651 {
652 NSCAP_LOG_ASSIGNMENT(this, 0);
653 assign_from_qi_with_error(qi, NS_GET_IID(T));
654 }
655
656 nsCOMPtr( const nsGetServiceByCID gs )
657 : NSCAP_CTOR_BASE(0)
658 // construct from |do_GetService(cid_expr)|
659 {
660 NSCAP_LOG_ASSIGNMENT(this, 0);
661 assign_from_gs_cid(gs, NS_GET_IID(T));
662 }
663
664 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
665 : NSCAP_CTOR_BASE(0)
666 // construct from |do_GetService(cid_expr, &rv)|
667 {
668 NSCAP_LOG_ASSIGNMENT(this, 0);
669 assign_from_gs_cid_with_error(gs, NS_GET_IID(T));
670 }
671
672 nsCOMPtr( const nsGetServiceByContractID gs )
673 : NSCAP_CTOR_BASE(0)
674 // construct from |do_GetService(contractid_expr)|
675 {
676 NSCAP_LOG_ASSIGNMENT(this, 0);
677 assign_from_gs_contractid(gs, NS_GET_IID(T));
678 }
679
680 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
681 : NSCAP_CTOR_BASE(0)
682 // construct from |do_GetService(contractid_expr, &rv)|
683 {
684 NSCAP_LOG_ASSIGNMENT(this, 0);
685 assign_from_gs_contractid_with_error(gs, NS_GET_IID(T));
686 }
687
688 nsCOMPtr( const nsCOMPtr_helper& helper )
689 : NSCAP_CTOR_BASE(0)
690 // ...and finally, anything else we might need to construct from
691 // can exploit the |nsCOMPtr_helper| facility
692 {
693 NSCAP_LOG_ASSIGNMENT(this, 0);
694 assign_from_helper(helper, NS_GET_IID(T));
695 NSCAP_ASSERT_NO_QUERY_NEEDED();
696 }
697
698
699 // Assignment operators
700
701 nsCOMPtr<T>&
702 operator=( const nsCOMPtr<T>& rhs )
703 // copy assignment operator
704 {
705 assign_with_AddRef(rhs.mRawPtr);
706 return *this;
707 }
708
709 nsCOMPtr<T>&
710 operator=( T* rhs )
711 // assign from a raw pointer (of the right type)
712 {
713 assign_with_AddRef(rhs);
714 NSCAP_ASSERT_NO_QUERY_NEEDED();
715 return *this;
716 }
717
718 nsCOMPtr<T>&
719 operator=( const already_AddRefed<T>& rhs )
720 // assign from |dont_AddRef(expr)|
721 {
722 assign_assuming_AddRef(rhs.mRawPtr);
723 NSCAP_ASSERT_NO_QUERY_NEEDED();
724 return *this;
725 }
726
727 nsCOMPtr<T>&
728 operator=( const nsQueryInterface rhs )
729 // assign from |do_QueryInterface(expr)|
730 {
731 assign_from_qi(rhs, NS_GET_IID(T));
732 return *this;
733 }
734
735 nsCOMPtr<T>&
736 operator=( const nsQueryInterfaceWithError& rhs )
737 // assign from |do_QueryInterface(expr, &rv)|
738 {
739 assign_from_qi_with_error(rhs, NS_GET_IID(T));
740 return *this;
741 }
742
743 nsCOMPtr<T>&
744 operator=( const nsGetServiceByCID rhs )
745 // assign from |do_GetService(cid_expr)|
746 {
747 assign_from_gs_cid(rhs, NS_GET_IID(T));
748 return *this;
749 }
750
751 nsCOMPtr<T>&
752 operator=( const nsGetServiceByCIDWithError& rhs )
753 // assign from |do_GetService(cid_expr, &rv)|
754 {
755 assign_from_gs_cid_with_error(rhs, NS_GET_IID(T));
756 return *this;
757 }
758
759 nsCOMPtr<T>&
760 operator=( const nsGetServiceByContractID rhs )
761 // assign from |do_GetService(contractid_expr)|
762 {
763 assign_from_gs_contractid(rhs, NS_GET_IID(T));
764 return *this;
765 }
766
767 nsCOMPtr<T>&
768 operator=( const nsGetServiceByContractIDWithError& rhs )
769 // assign from |do_GetService(contractid_expr, &rv)|
770 {
771 assign_from_gs_contractid_with_error(rhs, NS_GET_IID(T));
772 return *this;
773 }
774
775 nsCOMPtr<T>&
776 operator=( const nsCOMPtr_helper& rhs )
777 // ...and finally, anything else we might need to assign from
778 // can exploit the |nsCOMPtr_helper| facility.
779 {
780 assign_from_helper(rhs, NS_GET_IID(T));
781 NSCAP_ASSERT_NO_QUERY_NEEDED();
782 return *this;
783 }
784
785 void
786 swap( nsCOMPtr<T>& rhs )
787 // ...exchange ownership with |rhs|; can save a pair of refcount opera tions
788 {
789 #ifdef NSCAP_FEATURE_USE_BASE
790 nsISupports* temp = rhs.mRawPtr;
791 #else
792 T* temp = rhs.mRawPtr;
793 #endif
794 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
795 NSCAP_LOG_ASSIGNMENT(this, temp);
796 NSCAP_LOG_RELEASE(this, mRawPtr);
797 NSCAP_LOG_RELEASE(&rhs, temp);
798 rhs.mRawPtr = mRawPtr;
799 mRawPtr = temp;
800 // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASS ERT_NO_QUERY_NEEDED|
801 }
802
803 void
804 swap( T*& rhs )
805 // ...exchange ownership with |rhs|; can save a pair of refcount opera tions
806 {
807 #ifdef NSCAP_FEATURE_USE_BASE
808 nsISupports* temp = rhs;
809 #else
810 T* temp = rhs;
811 #endif
812 NSCAP_LOG_ASSIGNMENT(this, temp);
813 NSCAP_LOG_RELEASE(this, mRawPtr);
814 rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
815 mRawPtr = temp;
816 NSCAP_ASSERT_NO_QUERY_NEEDED();
817 }
818
819
820 // Other pointer operators
821
822 nsDerivedSafe<T>*
823 get() const
824 /*
825 Prefer the implicit conversion provided automatically by |operator n sDerivedSafe<T>*() const|.
826 Use |get()| _only_ to resolve ambiguity.
827
828 Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| an d |Release|.
829 */
830 {
831 return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
832 }
833
834 operator nsDerivedSafe<T>*() const
835 /*
836 ...makes an |nsCOMPtr| act like its underlying raw pointer type (exc ept against |AddRef()|, |Release()|,
837 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
838 that makes an |nsCOMPtr| substitutable for a raw pointer.
839
840 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
841 */
842 {
843 return get();
844 }
845
846 nsDerivedSafe<T>*
847 operator->() const
848 {
849 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr w ith operator->().");
850 return get();
851 }
852
853 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
854 // broken version for IRIX
855
856 nsCOMPtr<T>*
857 get_address() const
858 // This is not intended to be used by clients. See |address_of|
859 // below.
860 {
861 return NS_CONST_CAST(nsCOMPtr<T>*, this);
862 }
863
864 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
865
866 nsCOMPtr<T>*
867 get_address()
868 // This is not intended to be used by clients. See |address_of|
869 // below.
870 {
871 return this;
872 }
873
874 const nsCOMPtr<T>*
875 get_address() const
876 // This is not intended to be used by clients. See |address_of|
877 // below.
878 {
879 return this;
880 }
881
882 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
883
884 public:
885 nsDerivedSafe<T>&
886 operator*() const
887 {
888 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr w ith operator*().");
889 return *get();
890 }
891
892 #if 0
893 private:
894 friend class nsGetterAddRefs<T>;
895 #endif
896
897 T**
898 StartAssignment()
899 {
900 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
901 return NS_REINTERPRET_CAST(T**, begin_assignment());
902 #else
903 assign_assuming_AddRef(0);
904 return NS_REINTERPRET_CAST(T**, &mRawPtr);
905 #endif
906 }
907 };
908
909
910
911 /*
912 Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupp orts>| the
913 same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' point er pointing
914 to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
915 to point to the single [XP]COM-correct |nsISupports| instance within an obje ct; extra
916 querying ensues. Clients need to be able to pass around arbitrary interface pointers,
917 without hassles, through intermediary code that doesn't know the exact type.
918 */
919
920 NS_SPECIALIZE_TEMPLATE
921 class nsCOMPtr<nsISupports>
922 : private nsCOMPtr_base
923 {
924 public:
925 typedef nsISupports element_type;
926
927 // Constructors
928
929 nsCOMPtr()
930 : nsCOMPtr_base(0)
931 // default constructor
932 {
933 NSCAP_LOG_ASSIGNMENT(this, 0);
934 }
935
936 nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
937 : nsCOMPtr_base(aSmartPtr.mRawPtr)
938 // copy constructor
939 {
940 if ( mRawPtr )
941 NSCAP_ADDREF(this, mRawPtr);
942 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
943 }
944
945 nsCOMPtr( nsISupports* aRawPtr )
946 : nsCOMPtr_base(aRawPtr)
947 // construct from a raw pointer (of the right type)
948 {
949 if ( mRawPtr )
950 NSCAP_ADDREF(this, mRawPtr);
951 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
952 }
953
954 nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
955 : nsCOMPtr_base(aSmartPtr.mRawPtr)
956 // construct from |dont_AddRef(expr)|
957 {
958 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
959 }
960
961 nsCOMPtr( const nsQueryInterface qi )
962 : nsCOMPtr_base(0)
963 // assign from |do_QueryInterface(expr)|
964 {
965 NSCAP_LOG_ASSIGNMENT(this, 0);
966 assign_from_qi(qi, NS_GET_IID(nsISupports));
967 }
968
969 nsCOMPtr( const nsQueryInterfaceWithError& qi )
970 : nsCOMPtr_base(0)
971 // assign from |do_QueryInterface(expr, &rv)|
972 {
973 NSCAP_LOG_ASSIGNMENT(this, 0);
974 assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
975 }
976
977 nsCOMPtr( const nsGetServiceByCID gs )
978 : nsCOMPtr_base(0)
979 // assign from |do_GetService(cid_expr)|
980 {
981 NSCAP_LOG_ASSIGNMENT(this, 0);
982 assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
983 }
984
985 nsCOMPtr( const nsGetServiceByCIDWithError& gs )
986 : nsCOMPtr_base(0)
987 // assign from |do_GetService(cid_expr, &rv)|
988 {
989 NSCAP_LOG_ASSIGNMENT(this, 0);
990 assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
991 }
992
993 nsCOMPtr( const nsGetServiceByContractID gs )
994 : nsCOMPtr_base(0)
995 // assign from |do_GetService(contractid_expr)|
996 {
997 NSCAP_LOG_ASSIGNMENT(this, 0);
998 assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
999 }
1000
1001 nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
1002 : nsCOMPtr_base(0)
1003 // assign from |do_GetService(contractid_expr, &rv)|
1004 {
1005 NSCAP_LOG_ASSIGNMENT(this, 0);
1006 assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
1007 }
1008
1009 nsCOMPtr( const nsCOMPtr_helper& helper )
1010 : nsCOMPtr_base(0)
1011 // ...and finally, anything else we might need to construct from
1012 // can exploit the |nsCOMPtr_helper| facility
1013 {
1014 NSCAP_LOG_ASSIGNMENT(this, 0);
1015 assign_from_helper(helper, NS_GET_IID(nsISupports));
1016 }
1017
1018
1019 // Assignment operators
1020
1021 nsCOMPtr<nsISupports>&
1022 operator=( const nsCOMPtr<nsISupports>& rhs )
1023 // copy assignment operator
1024 {
1025 assign_with_AddRef(rhs.mRawPtr);
1026 return *this;
1027 }
1028
1029 nsCOMPtr<nsISupports>&
1030 operator=( nsISupports* rhs )
1031 // assign from a raw pointer (of the right type)
1032 {
1033 assign_with_AddRef(rhs);
1034 return *this;
1035 }
1036
1037 nsCOMPtr<nsISupports>&
1038 operator=( const already_AddRefed<nsISupports>& rhs )
1039 // assign from |dont_AddRef(expr)|
1040 {
1041 assign_assuming_AddRef(rhs.mRawPtr);
1042 return *this;
1043 }
1044
1045 nsCOMPtr<nsISupports>&
1046 operator=( const nsQueryInterface rhs )
1047 // assign from |do_QueryInterface(expr)|
1048 {
1049 assign_from_qi(rhs, NS_GET_IID(nsISupports));
1050 return *this;
1051 }
1052
1053 nsCOMPtr<nsISupports>&
1054 operator=( const nsQueryInterfaceWithError& rhs )
1055 // assign from |do_QueryInterface(expr, &rv)|
1056 {
1057 assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
1058 return *this;
1059 }
1060
1061 nsCOMPtr<nsISupports>&
1062 operator=( const nsGetServiceByCID rhs )
1063 // assign from |do_GetService(cid_expr)|
1064 {
1065 assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
1066 return *this;
1067 }
1068
1069 nsCOMPtr<nsISupports>&
1070 operator=( const nsGetServiceByCIDWithError& rhs )
1071 // assign from |do_GetService(cid_expr, &rv)|
1072 {
1073 assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
1074 return *this;
1075 }
1076
1077 nsCOMPtr<nsISupports>&
1078 operator=( const nsGetServiceByContractID rhs )
1079 // assign from |do_GetService(contractid_expr)|
1080 {
1081 assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
1082 return *this;
1083 }
1084
1085 nsCOMPtr<nsISupports>&
1086 operator=( const nsGetServiceByContractIDWithError& rhs )
1087 // assign from |do_GetService(contractid_expr, &rv)|
1088 {
1089 assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
1090 return *this;
1091 }
1092
1093 nsCOMPtr<nsISupports>&
1094 operator=( const nsCOMPtr_helper& rhs )
1095 // ...and finally, anything else we might need to assign from
1096 // can exploit the |nsCOMPtr_helper| facility.
1097 {
1098 assign_from_helper(rhs, NS_GET_IID(nsISupports));
1099 return *this;
1100 }
1101
1102 void
1103 swap( nsCOMPtr<nsISupports>& rhs )
1104 // ...exchange ownership with |rhs|; can save a pair of refcount opera tions
1105 {
1106 nsISupports* temp = rhs.mRawPtr;
1107 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
1108 NSCAP_LOG_ASSIGNMENT(this, temp);
1109 NSCAP_LOG_RELEASE(this, mRawPtr);
1110 NSCAP_LOG_RELEASE(&rhs, temp);
1111 rhs.mRawPtr = mRawPtr;
1112 mRawPtr = temp;
1113 }
1114
1115 void
1116 swap( nsISupports*& rhs )
1117 // ...exchange ownership with |rhs|; can save a pair of refcount opera tions
1118 {
1119 nsISupports* temp = rhs;
1120 NSCAP_LOG_ASSIGNMENT(this, temp);
1121 NSCAP_LOG_RELEASE(this, mRawPtr);
1122 rhs = mRawPtr;
1123 mRawPtr = temp;
1124 }
1125
1126
1127 // Other pointer operators
1128
1129 nsDerivedSafe<nsISupports>*
1130 get() const
1131 /*
1132 Prefer the implicit conversion provided automatically by |operator n sDerivedSafe<nsISupports>*() const|.
1133 Use |get()| _only_ to resolve ambiguity.
1134
1135 Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of | AddRef| and |Release|.
1136 */
1137 {
1138 return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
1139 }
1140
1141 operator nsDerivedSafe<nsISupports>*() const
1142 /*
1143 ...makes an |nsCOMPtr| act like its underlying raw pointer type (exc ept against |AddRef()|, |Release()|,
1144 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
1145 that makes an |nsCOMPtr| substitutable for a raw pointer.
1146
1147 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
1148 */
1149 {
1150 return get();
1151 }
1152
1153 nsDerivedSafe<nsISupports>*
1154 operator->() const
1155 {
1156 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr w ith operator->().");
1157 return get();
1158 }
1159
1160 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1161 // broken version for IRIX
1162
1163 nsCOMPtr<nsISupports>*
1164 get_address() const
1165 // This is not intended to be used by clients. See |address_of|
1166 // below.
1167 {
1168 return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
1169 }
1170
1171 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1172
1173 nsCOMPtr<nsISupports>*
1174 get_address()
1175 // This is not intended to be used by clients. See |address_of|
1176 // below.
1177 {
1178 return this;
1179 }
1180
1181 const nsCOMPtr<nsISupports>*
1182 get_address() const
1183 // This is not intended to be used by clients. See |address_of|
1184 // below.
1185 {
1186 return this;
1187 }
1188
1189 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1190
1191 public:
1192
1193 nsDerivedSafe<nsISupports>&
1194 operator*() const
1195 {
1196 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr w ith operator*().");
1197 return *get();
1198 }
1199
1200 #if 0
1201 private:
1202 friend class nsGetterAddRefs<nsISupports>;
1203 #endif
1204
1205 nsISupports**
1206 StartAssignment()
1207 {
1208 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1209 return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
1210 #else
1211 assign_assuming_AddRef(0);
1212 return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
1213 #endif
1214 }
1215 };
1216
1217 #ifndef NSCAP_FEATURE_USE_BASE
1218 template <class T>
1219 void
1220 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
1221 {
1222 if ( rawPtr )
1223 NSCAP_ADDREF(this, rawPtr);
1224 assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
1225 }
1226
1227 template <class T>
1228 void
1229 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
1230 {
1231 T* newRawPtr;
1232 if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1233 newRawPtr = 0;
1234 assign_assuming_AddRef(newRawPtr);
1235 }
1236
1237 template <class T>
1238 void
1239 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, con st nsIID& aIID )
1240 {
1241 T* newRawPtr;
1242 if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1243 newRawPtr = 0;
1244 assign_assuming_AddRef(newRawPtr);
1245 }
1246
1247 template <class T>
1248 void
1249 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
1250 {
1251 T* newRawPtr;
1252 if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1253 newRawPtr = 0;
1254 assign_assuming_AddRef(newRawPtr);
1255 }
1256
1257 template <class T>
1258 void
1259 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs , const nsIID& aIID )
1260 {
1261 T* newRawPtr;
1262 if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1263 newRawPtr = 0;
1264 assign_assuming_AddRef(newRawPtr);
1265 }
1266
1267 template <class T>
1268 void
1269 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
1270 {
1271 T* newRawPtr;
1272 if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1273 newRawPtr = 0;
1274 assign_assuming_AddRef(newRawPtr);
1275 }
1276
1277 template <class T>
1278 void
1279 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractI DWithError& gs, const nsIID& aIID )
1280 {
1281 T* newRawPtr;
1282 if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1283 newRawPtr = 0;
1284 assign_assuming_AddRef(newRawPtr);
1285 }
1286
1287 template <class T>
1288 void
1289 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aII D )
1290 {
1291 T* newRawPtr;
1292 if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1293 newRawPtr = 0;
1294 assign_assuming_AddRef(newRawPtr);
1295 }
1296
1297 template <class T>
1298 void**
1299 nsCOMPtr<T>::begin_assignment()
1300 {
1301 assign_assuming_AddRef(0);
1302 return NS_REINTERPRET_CAST(void**, &mRawPtr);
1303 }
1304 #endif
1305
1306 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1307
1308 // This is the broken version for IRIX, which can't handle the version below.
1309
1310 template <class T>
1311 inline
1312 nsCOMPtr<T>*
1313 address_of( const nsCOMPtr<T>& aPtr )
1314 {
1315 return aPtr.get_address();
1316 }
1317
1318 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1319
1320 template <class T>
1321 inline
1322 nsCOMPtr<T>*
1323 address_of( nsCOMPtr<T>& aPtr )
1324 {
1325 return aPtr.get_address();
1326 }
1327
1328 template <class T>
1329 inline
1330 const nsCOMPtr<T>*
1331 address_of( const nsCOMPtr<T>& aPtr )
1332 {
1333 return aPtr.get_address();
1334 }
1335
1336 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1337
1338 template <class T>
1339 class nsGetterAddRefs
1340 /*
1341 ...
1342
1343 This class is designed to be used for anonymous temporary objects in the
1344 argument list of calls that return COM interface pointers, e.g.,
1345
1346 nsCOMPtr<IFoo> fooP;
1347 ...->QueryInterface(iid, getter_AddRefs(fooP))
1348
1349 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instea d.
1350
1351 When initialized with a |nsCOMPtr|, as in the example above, it returns
1352 a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
1353 case) can fill in.
1354
1355 This type should be a nested class inside |nsCOMPtr<T>|.
1356 */
1357 {
1358 public:
1359 explicit
1360 nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
1361 : mTargetSmartPtr(aSmartPtr)
1362 {
1363 // nothing else to do
1364 }
1365
1366 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_AS SIGNMENT)
1367 ~nsGetterAddRefs()
1368 {
1369 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1370 NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSma rtPtr)), mTargetSmartPtr.get());
1371 #endif
1372
1373 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1374 mTargetSmartPtr.Assert_NoQueryNeeded();
1375 #endif
1376 }
1377 #endif
1378
1379 operator void**()
1380 {
1381 return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
1382 }
1383
1384 operator nsISupports**()
1385 {
1386 return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignm ent());
1387 }
1388
1389 operator T**()
1390 {
1391 return mTargetSmartPtr.StartAssignment();
1392 }
1393
1394 T*&
1395 operator*()
1396 {
1397 return *(mTargetSmartPtr.StartAssignment());
1398 }
1399
1400 private:
1401 nsCOMPtr<T>& mTargetSmartPtr;
1402 };
1403
1404
1405 NS_SPECIALIZE_TEMPLATE
1406 class nsGetterAddRefs<nsISupports>
1407 {
1408 public:
1409 explicit
1410 nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
1411 : mTargetSmartPtr(aSmartPtr)
1412 {
1413 // nothing else to do
1414 }
1415
1416 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1417 ~nsGetterAddRefs()
1418 {
1419 NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSma rtPtr)), mTargetSmartPtr.get());
1420 }
1421 #endif
1422
1423 operator void**()
1424 {
1425 return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
1426 }
1427
1428 operator nsISupports**()
1429 {
1430 return mTargetSmartPtr.StartAssignment();
1431 }
1432
1433 nsISupports*&
1434 operator*()
1435 {
1436 return *(mTargetSmartPtr.StartAssignment());
1437 }
1438
1439 private:
1440 nsCOMPtr<nsISupports>& mTargetSmartPtr;
1441 };
1442
1443
1444 template <class T>
1445 inline
1446 nsGetterAddRefs<T>
1447 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
1448 /*
1449 Used around a |nsCOMPtr| when
1450 ...makes the class |nsGetterAddRefs<T>| invisible.
1451 */
1452 {
1453 return nsGetterAddRefs<T>(aSmartPtr);
1454 }
1455
1456
1457
1458 // Comparing two |nsCOMPtr|s
1459
1460 template <class T, class U>
1461 inline
1462 NSCAP_BOOL
1463 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1464 {
1465 return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.g et());
1466 }
1467
1468
1469 template <class T, class U>
1470 inline
1471 NSCAP_BOOL
1472 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1473 {
1474 return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.g et());
1475 }
1476
1477
1478 // Comparing an |nsCOMPtr| to a raw pointer
1479
1480 template <class T, class U>
1481 inline
1482 NSCAP_BOOL
1483 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
1484 {
1485 return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
1486 }
1487
1488 template <class T, class U>
1489 inline
1490 NSCAP_BOOL
1491 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
1492 {
1493 return lhs == NS_STATIC_CAST(const T*, rhs.get());
1494 }
1495
1496 template <class T, class U>
1497 inline
1498 NSCAP_BOOL
1499 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
1500 {
1501 return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
1502 }
1503
1504 template <class T, class U>
1505 inline
1506 NSCAP_BOOL
1507 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
1508 {
1509 return lhs != NS_STATIC_CAST(const T*, rhs.get());
1510 }
1511
1512 // To avoid ambiguities caused by the presence of builtin |operator==|s
1513 // creating a situation where one of the |operator==| defined above
1514 // has a better conversion for one argument and the builtin has a
1515 // better conversion for the other argument, define additional
1516 // |operator==| without the |const| on the raw pointer.
1517 // See bug 65664 for details.
1518
1519 // This is defined by an autoconf test, but VC++ also has a bug that
1520 // prevents us from using these. (It also, fortunately, has the bug
1521 // that we don't need them either.)
1522 #if defined(_MSC_VER) && (_MSC_VER < 1310)
1523 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1524 #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1525 #endif
1526 #endif
1527
1528 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1529 template <class T, class U>
1530 inline
1531 NSCAP_BOOL
1532 operator==( const nsCOMPtr<T>& lhs, U* rhs )
1533 {
1534 return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
1535 }
1536
1537 template <class T, class U>
1538 inline
1539 NSCAP_BOOL
1540 operator==( U* lhs, const nsCOMPtr<T>& rhs )
1541 {
1542 return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
1543 }
1544
1545 template <class T, class U>
1546 inline
1547 NSCAP_BOOL
1548 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
1549 {
1550 return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
1551 }
1552
1553 template <class T, class U>
1554 inline
1555 NSCAP_BOOL
1556 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
1557 {
1558 return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
1559 }
1560 #endif
1561
1562
1563
1564 // Comparing an |nsCOMPtr| to |0|
1565
1566 class NSCAP_Zero;
1567
1568 template <class T>
1569 inline
1570 NSCAP_BOOL
1571 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1572 // specifically to allow |smartPtr == 0|
1573 {
1574 return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const v oid*, rhs);
1575 }
1576
1577 template <class T>
1578 inline
1579 NSCAP_BOOL
1580 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1581 // specifically to allow |0 == smartPtr|
1582 {
1583 return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
1584 }
1585
1586 template <class T>
1587 inline
1588 NSCAP_BOOL
1589 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1590 // specifically to allow |smartPtr != 0|
1591 {
1592 return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const v oid*, rhs);
1593 }
1594
1595 template <class T>
1596 inline
1597 NSCAP_BOOL
1598 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1599 // specifically to allow |0 != smartPtr|
1600 {
1601 return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
1602 }
1603
1604
1605 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1606
1607 // We need to explicitly define comparison operators for `int'
1608 // because the compiler is lame.
1609
1610 template <class T>
1611 inline
1612 NSCAP_BOOL
1613 operator==( const nsCOMPtr<T>& lhs, int rhs )
1614 // specifically to allow |smartPtr == 0|
1615 {
1616 return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const v oid*, rhs);
1617 }
1618
1619 template <class T>
1620 inline
1621 NSCAP_BOOL
1622 operator==( int lhs, const nsCOMPtr<T>& rhs )
1623 // specifically to allow |0 == smartPtr|
1624 {
1625 return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
1626 }
1627
1628 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1629
1630 // Comparing any two [XP]COM objects for identity
1631
1632 inline
1633 NSCAP_BOOL
1634 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
1635 {
1636 return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISuppor ts>( do_QueryInterface(rhs) );
1637 }
1638
1639
1640
1641 template <class SourceType, class DestinationType>
1642 inline
1643 nsresult
1644 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
1645 {
1646 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1647 }
1648
1649 #endif // !defined(nsCOMPtr_h___)
OLDNEW
« no previous file with comments | « gecko-sdk/include/nsBuildID.h ('k') | gecko-sdk/include/nsComponentManagerUtils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698