Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/alloca.h>
21 :
22 : #include <string.h>
23 : #include <osl/diagnose.h>
24 : #include <rtl/byteseq.hxx>
25 : #include <rtl/ustrbuf.hxx>
26 : #include <rtl/uuid.h>
27 : #include <cppuhelper/compbase_ex.hxx>
28 :
29 : #include <com/sun/star/uno/RuntimeException.hpp>
30 :
31 : using namespace ::cppu;
32 : using namespace ::osl;
33 : using namespace ::com::sun::star;
34 : using namespace ::com::sun::star::uno;
35 :
36 : using rtl::OString;
37 : using rtl::OUString;
38 : using rtl::OUStringBuffer;
39 :
40 : namespace
41 : {
42 : class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
43 : }
44 :
45 : namespace cppu
46 : {
47 :
48 : /** Shared mutex for implementation helper initialization.
49 : Not for public use.
50 : */
51 51322 : ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void)
52 : {
53 51322 : return theImplHelperInitMutex::get();
54 : }
55 :
56 :
57 73817607 : static inline void checkInterface( Type const & rType )
58 : {
59 73817607 : if (TypeClass_INTERFACE != rType.getTypeClass())
60 : {
61 0 : OUString msg( "querying for interface \"" + rType.getTypeName() + "\": no interface type!" );
62 : SAL_WARN( "cppuhelper", msg );
63 0 : throw RuntimeException( msg );
64 : }
65 73817619 : }
66 :
67 51099433 : static inline bool isXInterface( rtl_uString * pStr )
68 : {
69 51099433 : return (*((OUString const *)&pStr) == "com.sun.star.uno.XInterface");
70 : }
71 :
72 35876200 : static inline void * makeInterface( sal_IntPtr nOffset, void * that )
73 : {
74 35876200 : return (((char *)that) + nOffset);
75 : }
76 :
77 411866304 : static inline bool __td_equals(
78 : typelib_TypeDescriptionReference const * pTDR1,
79 : typelib_TypeDescriptionReference const * pTDR2 )
80 : {
81 787995881 : return ((pTDR1 == pTDR2) ||
82 787995881 : ((OUString const *)&pTDR1->pTypeName)->equals( *(OUString const *)&pTDR2->pTypeName ));
83 : }
84 :
85 70555790 : static inline type_entry * __getTypeEntries( class_data * cd )
86 : {
87 70555790 : type_entry * pEntries = cd->m_typeEntries;
88 70555790 : if (! cd->m_storedTypeRefs) // not inited?
89 : {
90 51322 : MutexGuard guard( getImplHelperInitMutex() );
91 51322 : if (! cd->m_storedTypeRefs) // not inited?
92 : {
93 : // get all types
94 303108 : for ( sal_Int32 n = cd->m_nTypes; n--; )
95 : {
96 200464 : type_entry * pEntry = &pEntries[ n ];
97 200464 : Type const & rType = (*pEntry->m_type.getCppuType)( 0 );
98 : OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
99 : OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
100 200464 : if (rType.getTypeClass() != TypeClass_INTERFACE)
101 : {
102 0 : OUString msg( "type \"" + rType.getTypeName() + "\" is no interface type!" );
103 : SAL_WARN( "cppuhelper", msg );
104 0 : throw RuntimeException( msg );
105 : }
106 : // ref is statically held by getCppuType()
107 200464 : pEntry->m_type.typeRef = rType.getTypeLibType();
108 : }
109 51322 : cd->m_storedTypeRefs = sal_True;
110 51322 : }
111 : }
112 70555790 : return pEntries;
113 : }
114 :
115 69956 : static inline void __fillTypes( Type * types, class_data * cd )
116 : {
117 69956 : type_entry * pEntries = __getTypeEntries( cd );
118 1488916 : for ( sal_Int32 n = cd->m_nTypes; n--; )
119 : {
120 1349004 : types[ n ] = pEntries[ n ].m_type.typeRef;
121 : }
122 69956 : }
123 :
124 : namespace {
125 :
126 247596131 : bool recursivelyFindType(
127 : typelib_TypeDescriptionReference const * demandedType,
128 : typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
129 : {
130 : // This code assumes that the vtables of a multiple-inheritance class (the
131 : // offset amount by which to adjust the this pointer) follow one another in
132 : // the object layout, and that they contain slots for the inherited classes
133 : // in a specific order. In theory, that need not hold for any given
134 : // platform; in practice, it seems to work well on all supported platforms:
135 : next:
136 450219566 : for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
137 251013429 : if (i > 0) {
138 3417313 : *offset += sizeof (void *);
139 : }
140 251013429 : typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
141 : // ignore XInterface:
142 251013429 : if (base->nBaseTypes > 0) {
143 52812036 : if (__td_equals(
144 : reinterpret_cast<
145 : typelib_TypeDescriptionReference const * >(base),
146 : demandedType))
147 : {
148 6561724 : return true;
149 : }
150 : // Profiling showed that it is important to speed up the common case
151 : // of only one base:
152 46250460 : if (type->nBaseTypes == 1) {
153 41654425 : type = base;
154 41654425 : goto next;
155 : }
156 4596035 : if (recursivelyFindType(demandedType, base, offset)) {
157 173996 : return true;
158 : }
159 : }
160 : }
161 199206137 : return false;
162 : }
163 :
164 : }
165 :
166 70485835 : static inline void * __queryDeepNoXInterface(
167 : typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that )
168 : {
169 70485835 : type_entry * pEntries = __getTypeEntries( cd );
170 70485672 : sal_Int32 nTypes = cd->m_nTypes;
171 : sal_Int32 n;
172 :
173 : // try top interfaces without getting td
174 400365028 : for ( n = 0; n < nTypes; ++n )
175 : {
176 359054443 : if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
177 : {
178 29175241 : return makeInterface( pEntries[ n ].m_offset, that );
179 : }
180 : }
181 : // query deep getting td
182 236094709 : for ( n = 0; n < nTypes; ++n )
183 : {
184 201345811 : typelib_TypeDescription * pTD = 0;
185 201345811 : TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
186 201345810 : if (pTD)
187 : {
188 : // exclude top (already tested) and bottom (XInterface) interface
189 : OSL_ENSURE(
190 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
191 : nBaseTypes > 0,
192 : "### want to implement XInterface:"
193 : " template argument is XInterface?!?!?!" );
194 201345810 : sal_IntPtr offset = pEntries[n].m_offset;
195 : bool found = recursivelyFindType(
196 : pDemandedTDR,
197 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
198 201345810 : &offset);
199 201345813 : TYPELIB_DANGER_RELEASE( pTD );
200 201345849 : if (found) {
201 6561725 : return makeInterface( offset, that );
202 : }
203 : }
204 : else
205 : {
206 0 : OUString msg( "cannot get type description for type \"" + OUString(pEntries[ n ].m_type.typeRef->pTypeName) + "\"!" );
207 : SAL_WARN( "cppuhelper", msg );
208 0 : throw RuntimeException( msg );
209 : }
210 : }
211 34748898 : return 0;
212 : }
213 :
214 : // ImplHelper
215 :
216 2786146 : Any SAL_CALL ImplHelper_query(
217 : Type const & rType, class_data * cd, void * that )
218 : {
219 2786146 : checkInterface( rType );
220 2786146 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
221 :
222 : void * p;
223 : // shortcut for XInterface
224 2786146 : if (isXInterface( pTDR->pTypeName ))
225 : {
226 : // take first one
227 139244 : p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
228 : }
229 : else
230 : {
231 2646902 : p = __queryDeepNoXInterface( pTDR, cd, that );
232 2646902 : if (! p)
233 : {
234 2227027 : return Any();
235 : }
236 : }
237 559119 : return Any( &p, pTDR );
238 : }
239 :
240 22718190 : Any SAL_CALL ImplHelper_queryNoXInterface(
241 : Type const & rType, class_data * cd, void * that )
242 : {
243 22718190 : checkInterface( rType );
244 22718190 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
245 :
246 22718190 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
247 22718189 : if (p)
248 : {
249 7222147 : return Any( &p, pTDR );
250 : }
251 : else
252 : {
253 15496042 : return Any();
254 : }
255 : }
256 :
257 12 : css::uno::Sequence<sal_Int8> ImplHelper_getImplementationId(
258 : SAL_UNUSED_PARAMETER class_data *)
259 : {
260 12 : return css::uno::Sequence<sal_Int8>();
261 : }
262 :
263 1598 : Sequence< Type > SAL_CALL ImplHelper_getTypes(
264 : class_data * cd )
265 : {
266 1598 : Sequence< Type > types( cd->m_nTypes );
267 1598 : Type * pTypes = types.getArray();
268 1598 : __fillTypes( pTypes, cd );
269 1598 : return types;
270 : }
271 :
272 2262 : Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
273 : class_data * cd, Sequence< Type > const & rAddTypes )
274 : {
275 2262 : sal_Int32 nImplTypes = cd->m_nTypes;
276 2262 : sal_Int32 nAddTypes = rAddTypes.getLength();
277 2262 : Sequence< Type > types( nImplTypes + nAddTypes );
278 2262 : Type * pTypes = types.getArray();
279 2262 : __fillTypes( pTypes, cd );
280 : // append base types
281 2262 : Type const * pAddTypes = rAddTypes.getConstArray();
282 18682 : while (nAddTypes--)
283 : {
284 14158 : pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
285 : }
286 2262 : return types;
287 : }
288 :
289 : // WeakImplHelper
290 :
291 35606600 : Any SAL_CALL WeakImplHelper_query(
292 : Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
293 : {
294 35606600 : checkInterface( rType );
295 35606603 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
296 :
297 : // shortcut XInterface to OWeakObject
298 35606602 : if (! isXInterface( pTDR->pTypeName ))
299 : {
300 33559773 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
301 33559786 : if (p)
302 : {
303 17731856 : return Any( &p, pTDR );
304 : }
305 : }
306 17874753 : return pBase->OWeakObject::queryInterface( rType );
307 : }
308 :
309 45684 : Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
310 : class_data * cd )
311 : {
312 45684 : sal_Int32 nTypes = cd->m_nTypes;
313 45684 : Sequence< Type > types( nTypes +1 );
314 45684 : Type * pTypes = types.getArray();
315 45684 : __fillTypes( pTypes, cd );
316 45684 : pTypes[ nTypes ] = ::getCppuType( (Reference< XWeak > const *)0 );
317 45684 : return types;
318 : }
319 :
320 : // WeakAggImplHelper
321 :
322 3722050 : Any SAL_CALL WeakAggImplHelper_queryAgg(
323 : Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
324 : {
325 3722050 : checkInterface( rType );
326 3722050 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
327 :
328 : // shortcut XInterface to OWeakAggObject
329 3722050 : if (! isXInterface( pTDR->pTypeName ))
330 : {
331 2752888 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
332 2752888 : if (p)
333 : {
334 2216110 : return Any( &p, pTDR );
335 : }
336 : }
337 1505940 : return pBase->OWeakAggObject::queryAggregation( rType );
338 : }
339 :
340 19620 : Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
341 : class_data * cd )
342 : {
343 19620 : sal_Int32 nTypes = cd->m_nTypes;
344 19620 : Sequence< Type > types( nTypes +2 );
345 19620 : Type * pTypes = types.getArray();
346 19620 : __fillTypes( pTypes, cd );
347 19620 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
348 19620 : pTypes[ nTypes ] = ::getCppuType( (const Reference< XAggregation > *)0 );
349 19620 : return types;
350 : }
351 :
352 : // WeakComponentImplHelper
353 :
354 8932538 : Any SAL_CALL WeakComponentImplHelper_query(
355 : Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
356 : {
357 8932538 : checkInterface( rType );
358 8932538 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
359 :
360 : // shortcut XInterface to WeakComponentImplHelperBase
361 8932538 : if (! isXInterface( pTDR->pTypeName ))
362 : {
363 8775246 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
364 8775244 : if (p)
365 : {
366 8144234 : return Any( &p, pTDR );
367 : }
368 : }
369 788302 : return pBase->WeakComponentImplHelperBase::queryInterface( rType );
370 : }
371 :
372 480 : Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
373 : class_data * cd )
374 : {
375 480 : sal_Int32 nTypes = cd->m_nTypes;
376 480 : Sequence< Type > types( nTypes +2 );
377 480 : Type * pTypes = types.getArray();
378 480 : __fillTypes( pTypes, cd );
379 480 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
380 480 : pTypes[ nTypes ] = ::getCppuType( (Reference< lang::XComponent > const *)0 );
381 480 : return types;
382 : }
383 :
384 : // WeakAggComponentImplHelper
385 :
386 52107 : Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
387 : Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
388 : {
389 52107 : checkInterface( rType );
390 52107 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
391 :
392 : // shortcut XInterface to WeakAggComponentImplHelperBase
393 52107 : if (! isXInterface( pTDR->pTypeName ))
394 : {
395 32863 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
396 32863 : if (p)
397 : {
398 2752 : return Any( &p, pTDR );
399 : }
400 : }
401 49355 : return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
402 : }
403 :
404 312 : Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
405 : class_data * cd )
406 : {
407 312 : sal_Int32 nTypes = cd->m_nTypes;
408 312 : Sequence< Type > types( nTypes +3 );
409 312 : Type * pTypes = types.getArray();
410 312 : __fillTypes( pTypes, cd );
411 312 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
412 312 : pTypes[ nTypes++ ] = ::getCppuType( (const Reference< XAggregation > *)0 );
413 312 : pTypes[ nTypes ] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
414 312 : return types;
415 : }
416 :
417 : }
418 :
419 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|