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