1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef _CPPUHELPER_IMPLBASE_HXX_
24 #define _CPPUHELPER_IMPLBASE_HXX_
25 
26 #include <osl/mutex.hxx>
27 #include <cppuhelper/weak.hxx>
28 #include <cppuhelper/weakagg.hxx>
29 #include <rtl/instance.hxx>
30 
31 #include <com/sun/star/lang/XTypeProvider.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 
34 #include "cppuhelper/cppuhelperdllapi.h"
35 
36 /* This header should not be used anymore.
37    @deprecated
38 */
39 
40 namespace cppu
41 {
42 
43 /** Struct used for inline template implementation helpers: type entries.
44     Not for plublic use.
45     @internal
46 */
47 struct Type_Offset
48 {
49     /** binary offset of vtable pointer from object base
50     */
51 	sal_Int32 nOffset;
52     /** interface type description of interface entry
53     */
54 	typelib_InterfaceTypeDescription * pTD;
55 };
56 /** Struct used for inline template implementation helpers: class data of implementation.
57     Not for plublic use.
58     @internal
59 */
60 struct CPPUHELPER_DLLPUBLIC ClassDataBase
61 {
62     /** determines whether the class data has been statically initialized
63     */
64 	sal_Bool  bOffsetsInit;
65     /** length of static array ClassDataN
66     */
67 	sal_Int32 nType2Offset;
68 
69     /** class code determines which standard types are supported (and returned on
70         com.sun.star.lang.XTypeProvider::getTypes()) by the helper:
71 
72         - 1 -- com.sun.star.uno.XWeak
73         - 2 -- com.sun.star.uno.XWeak, com.sun.star.uno.XAggregation
74         - 3 -- com.sun.star.uno.XWeak, com.sun.star.uno.XAggregation, com.sun.star.lang.XComponent
75         - 4 -- com.sun.star.uno.XWeak, com.sun.star.lang.XComponent
76     */
77 	sal_Int32 nClassCode;
78 
79     /** pointer to types sequence (com.sun.star.lang.XTypeProvider)
80     */
81 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > * pTypes;
82     /** pointer to class id (com.sun.star.lang.XTypeProvider)
83     */
84 	::com::sun::star::uno::Sequence< sal_Int8 > * pId;
85 
86     /** def ctor
87     */
88 	ClassDataBase() SAL_THROW( () );
89     /** class code ctor
90 
91         @param nClassCode class code, see ClassDataBase::nClassCode
92     */
93 	ClassDataBase( sal_Int32 nClassCode ) SAL_THROW( () );
94     /** dtor
95     */
96 	~ClassDataBase() SAL_THROW( () );
97 };
98 /** Struct used for inline template implementation helpers:
99     There will be versions of this struct with varying arType2Offset[] array sizes, each of which
100     is binary compatible with this one to be casted and used uniform. The size of the varying array
101     is set in ClassDataBase::nType2Offset (base class).
102     Not for plublic use.
103     @internal
104 */
105 struct CPPUHELPER_DLLPUBLIC ClassData : public ClassDataBase
106 {
107     /** type entries array
108     */
109 	Type_Offset arType2Offset[1];
110 
111     /** init call for supporting com.sun.star.lang.XTypeProvider
112     */
113 	void SAL_CALL initTypeProvider() SAL_THROW( () );
114     /** initial writing type offsets for vtables
115 
116         @param rType type of interface
117         @param nOffset offset to vtable entry
118     */
119 	void SAL_CALL writeTypeOffset( const ::com::sun::star::uno::Type & rType, sal_Int32 nOffset )
120 		SAL_THROW( () );
121 
122     /** Queries for an interface.
123 
124         @param rType demanded interface type
125         @pBase base this pointer related when writing type offsets (writeTypeOffset())
126         @return demanded interface or empty any
127     */
128 	::com::sun::star::uno::Any SAL_CALL query(
129 		const ::com::sun::star::uno::Type & rType, ::com::sun::star::lang::XTypeProvider * pBase )
130 		SAL_THROW( () );
131     /** Gets the types for supporting com.sun.star.lang.XTypeProvider
132 
133         @return sequence of types supported
134     */
135 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes()
136 		SAL_THROW( () );
137     /** Gets the class id of implemtation supporting com.sun.star.lang.XTypeProvider
138 
139         @return class identifier (sequence< byte >)
140     */
141 	::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId()
142 		SAL_THROW( () );
143 };
144 
145 /** Shared mutex for implementation helper initialization.
146     Not for public use.
147     @internal
148 */
149 CPPUHELPER_DLLPUBLIC ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW( () );
150 }
151 
152 //
153 // settle down beavis, here comes the macro template hell :]
154 //
155 
156 //==================================================================================================
157 
158 /** Implementation helper macros
159     Not for common use. There are expanded forms of the macro usage in implbaseN.hxx/compbaseN.hxx.
160     So there is commonly no need to use these macros. Though, you may need to implement more than
161     12 interfaces. Then you have to declare something like the following in your headers
162     (where N is your demanded number of interfaces):
163 
164     #define __IFC3 Ifc1, Ifc2, Ifc3, ... up to N
165     #define __CLASS_IFC3 class Ifc1, class Ifc2, class Ifc3, ... up to N
166     #define __PUBLIC_IFC3 public Ifc1, public Ifc2, public Ifc3, ... up to N
167     __DEF_IMPLHELPER_PRE( N )
168 	__IFC_WRITEOFFSET( 1 ) __IFC_WRITEOFFSET( 2 ) __IFC_WRITEOFFSET( 3 ), ... up to N
169     __DEF_IMPLHELPER_POST( N )
170 
171     @internal
172 */
173 #define __DEF_IMPLHELPER_PRE( N ) \
174 namespace cppu \
175 { \
176 struct ClassData##N : public ClassDataBase \
177 { \
178 	Type_Offset arType2Offset[ N ]; \
179 	ClassData##N( sal_Int32 nClassCode ) SAL_THROW( () ) \
180 		: ClassDataBase( nClassCode ) \
181 		{} \
182 }; \
183 template< __CLASS_IFC##N > \
184 class SAL_NO_VTABLE ImplHelperBase##N \
185 	: public ::com::sun::star::lang::XTypeProvider \
186 	, __PUBLIC_IFC##N \
187 { \
188 protected: \
189 	ClassData & SAL_CALL getClassData( ClassDataBase & s_aCD ) SAL_THROW( () ) \
190 	{ \
191 		ClassData & rCD = * static_cast< ClassData * >( &s_aCD ); \
192 		if (! rCD.bOffsetsInit) \
193 		{ \
194 			::osl::MutexGuard aGuard( getImplHelperInitMutex() ); \
195 			if (! rCD.bOffsetsInit) \
196 			{ \
197 				char * pBase = (char *)this;
198 /** Implementation helper macro: have a look at __DEF_IMPLHELPER_PRE
199     @internal
200 */
201 #define __IFC_WRITEOFFSET( N ) \
202 				rCD.writeTypeOffset( ::getCppuType( (const ::com::sun::star::uno::Reference< Ifc##N > *)0 ), \
203 									 (char *)(Ifc##N *)this - pBase );
204 /** Implementation helper macro: have a look at __DEF_IMPLHELPER_PRE
205     @internal
206 */
207 #define __DEF_IMPLHELPER_POST_A( N ) \
208 				rCD.bOffsetsInit = sal_True; \
209 			} \
210 		} \
211 		return rCD; \
212 	} \
213 }; \
214 template< __CLASS_IFC##N > \
215 class SAL_NO_VTABLE ImplHelper##N \
216 	: public ImplHelperBase##N< __IFC##N > \
217 { \
218 	static ClassData##N s_aCD; \
219 public: \
220 	virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException) \
221 		{ return this->getClassData( s_aCD ).query( rType, (ImplHelperBase##N< __IFC##N > *)this ); } \
222 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException) \
223 		{ return this->getClassData( s_aCD ).getTypes(); } \
224 	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) \
225 		{ return this->getClassData( s_aCD ).getImplementationId(); } \
226 }; \
227 template< __CLASS_IFC##N > \
228 class SAL_NO_VTABLE WeakImplHelper##N \
229 	: public ::cppu::OWeakObject \
230 	, public ImplHelperBase##N< __IFC##N > \
231 { \
232 	static ClassData##N s_aCD; \
233 public: \
234 	virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException) \
235 	{ \
236 		::com::sun::star::uno::Any aRet( this->getClassData( s_aCD ).query( rType, (ImplHelperBase##N< __IFC##N > *)this ) ); \
237 		return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType )); \
238 	} \
239 	virtual void SAL_CALL acquire() throw () \
240 		{ OWeakObject::acquire(); } \
241 	virtual void SAL_CALL release() throw () \
242 		{ OWeakObject::release(); } \
243 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException) \
244 		{ return this->getClassData( s_aCD ).getTypes(); } \
245 	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) \
246 		{ return this->getClassData( s_aCD ).getImplementationId(); } \
247 }; \
248 template< __CLASS_IFC##N > \
249 class SAL_NO_VTABLE WeakAggImplHelper##N \
250 	: public ::cppu::OWeakAggObject \
251 	, public ImplHelperBase##N< __IFC##N > \
252 { \
253 	static ClassData##N s_aCD; \
254 public: \
255 	virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException) \
256 		{ return OWeakAggObject::queryInterface( rType ); } \
257 	virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException) \
258 	{ \
259 		::com::sun::star::uno::Any aRet( this->getClassData( s_aCD ).query( rType, (ImplHelperBase##N< __IFC##N > *)this ) ); \
260 		return (aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( rType )); \
261 	} \
262 	virtual void SAL_CALL acquire() throw () \
263 		{ OWeakAggObject::acquire(); } \
264 	virtual void SAL_CALL release() throw () \
265 		{ OWeakAggObject::release(); } \
266 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException) \
267 		{ return this->getClassData( s_aCD ).getTypes(); } \
268 	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) \
269 		{ return this->getClassData( s_aCD ).getImplementationId(); } \
270 };
271 
272 /** Implementation helper macro: have a look at __DEF_IMPLHELPER_PRE
273     @internal
274 */
275 #define __DEF_IMPLHELPER_POST_B( N ) \
276 template< __CLASS_IFC##N > \
277 ClassData##N ImplHelper##N< __IFC##N >::s_aCD = ClassData##N( 0 ); \
278 template< __CLASS_IFC##N > \
279 ClassData##N WeakImplHelper##N< __IFC##N >::s_aCD = ClassData##N( 1 ); \
280 template< __CLASS_IFC##N > \
281 ClassData##N WeakAggImplHelper##N< __IFC##N >::s_aCD = ClassData##N( 2 );
282 /** Implementation helper macro: have a look at __DEF_IMPLHELPER_PRE
283     @internal
284 */
285 #define __DEF_IMPLHELPER_POST_C( N ) \
286 }
287 //==================================================================================================
288 /** Implementation helper macro: have a look at __DEF_IMPLHELPER_PRE
289     @internal
290 */
291 #define __DEF_IMPLHELPER_POST( N ) \
292 __DEF_IMPLHELPER_POST_A( N ) \
293 __DEF_IMPLHELPER_POST_B( N ) \
294 __DEF_IMPLHELPER_POST_C( N )
295 #endif
296 
297