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