Back to index

lightning-sunbird  0.9+nobinonly
nsISupportsUtils.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *   Scott Collins <scc@ScottCollins.net>
00025  *   Dan Mosedale <dmose@mozilla.org>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #ifndef nsISupportsUtils_h__
00042 #define nsISupportsUtils_h__
00043 
00044 #ifndef nscore_h___
00045 #include "nscore.h"
00046 #endif
00047 
00048 #ifndef nsISupportsBase_h__
00049 #include "nsISupportsBase.h"
00050 #endif
00051 
00052 #ifndef nsError_h__
00053 #include "nsError.h"
00054 #endif
00055 
00056 #ifndef nsDebug_h___
00057 #include "nsDebug.h"
00058 #endif
00059 
00060 #ifndef nsISupportsImpl_h__
00061 #include "nsISupportsImpl.h"
00062 #endif
00063 
00071 #define NS_NEWXPCOM(_result,_type)                                            \
00072   PR_BEGIN_MACRO                                                              \
00073     _result = new _type();                                                    \
00074   PR_END_MACRO
00075 
00080 #define NS_DELETEXPCOM(_ptr)                                                  \
00081   PR_BEGIN_MACRO                                                              \
00082     delete (_ptr);                                                            \
00083   PR_END_MACRO
00084 
00089 #define NS_ADDREF(_ptr) \
00090   (_ptr)->AddRef()
00091 
00098 #define NS_ADDREF_THIS() \
00099   AddRef()
00100 
00101 
00102 extern "C++" {
00103 // ...because some one is accidentally including this file inside
00104 // an |extern "C"|
00105 
00106 
00107 // Making this a |inline| |template| allows |expr| to be evaluated only once,
00108 // yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
00109 template <class T>
00110 inline
00111 nsrefcnt
00112 ns_if_addref( T expr )
00113 {
00114     return expr ? expr->AddRef() : 0;
00115 }
00116 
00117 } /* extern "C++" */
00118 
00123 #define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
00124 
00125 /*
00126  * Given these declarations, it explicitly OK and efficient to end a `getter' with:
00127  *
00128  *    NS_IF_ADDREF(*result = mThing);
00129  *
00130  * even if |mThing| is an |nsCOMPtr|.  If |mThing| is an |nsCOMPtr|, however, it is still
00131  * _illegal_ to say |NS_IF_ADDREF(mThing)|.
00132  */
00133 
00138 #define NS_RELEASE(_ptr)                                                      \
00139   PR_BEGIN_MACRO                                                              \
00140     (_ptr)->Release();                                                        \
00141     (_ptr) = 0;                                                               \
00142   PR_END_MACRO
00143 
00148 #define NS_RELEASE_THIS() \
00149     Release()
00150 
00159 #define NS_RELEASE2(_ptr,_rv)                                                 \
00160   PR_BEGIN_MACRO                                                              \
00161     _rv = (_ptr)->Release();                                                  \
00162     if (0 == (_rv)) (_ptr) = 0;                                               \
00163   PR_END_MACRO
00164 
00169 #define NS_IF_RELEASE(_ptr)                                                   \
00170   PR_BEGIN_MACRO                                                              \
00171     if (_ptr) {                                                               \
00172       (_ptr)->Release();                                                      \
00173       (_ptr) = 0;                                                             \
00174     }                                                                         \
00175   PR_END_MACRO
00176 
00177 /*
00178  * Often you have to cast an implementation pointer, e.g., |this|, to an
00179  * |nsISupports*|, but because you have multiple inheritance, a simple cast
00180  * is ambiguous.  One could simply say, e.g., (given a base |nsIBase|),
00181  * |NS_STATIC_CAST(nsIBase*, this)|; but that disguises the fact that what
00182  * you are really doing is disambiguating the |nsISupports|.  You could make
00183  * that more obvious with a double cast, e.g., |NS_STATIC_CAST(nsISupports*,
00184  * NS_STATIC_CAST(nsIBase*, this))|, but that is bulky and harder to read...
00185  *
00186  * The following macro is clean, short, and obvious.  In the example above,
00187  * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
00188  */
00189 
00190 #define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
00191   NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(__unambiguousBase, __expr))
00192 
00193 extern "C++" {
00194 // ...because some one is accidentally including this file inside
00195 // an |extern "C"|
00196 
00197 class nsISupports;
00198 
00199 template <class T>
00200 struct nsCOMTypeInfo
00201 {
00202     static const nsIID& GetIID() { return T::GetIID(); }
00203 };
00204 
00205 NS_SPECIALIZE_TEMPLATE
00206 struct nsCOMTypeInfo<nsISupports>
00207 {
00208     static const nsIID& GetIID() {
00209         static const nsIID iid_NS_ISUPPORTS_IID = NS_ISUPPORTS_IID; return iid_NS_ISUPPORTS_IID;
00210     }
00211 };
00212 
00213 #define NS_GET_IID(T) nsCOMTypeInfo<T>::GetIID()
00214 
00215 // a type-safe shortcut for calling the |QueryInterface()| member function
00216 template <class T, class DestinationType>
00217 inline
00218 nsresult
00219 CallQueryInterface( T* aSource, DestinationType** aDestination )
00220 {
00221     NS_PRECONDITION(aSource, "null parameter");
00222     NS_PRECONDITION(aDestination, "null parameter");
00223     
00224     return aSource->QueryInterface(NS_GET_IID(DestinationType),
00225                                    NS_REINTERPRET_CAST(void**, aDestination));
00226 }
00227 
00228 } // extern "C++"
00229 
00230 #endif /* __nsISupportsUtils_h */