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 <sal/log.hxx>
28 : #include <cppuhelper/compbase_ex.hxx>
29 :
30 : #include <com/sun/star/uno/RuntimeException.hpp>
31 :
32 : using namespace ::cppu;
33 : using namespace ::osl;
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::uno;
36 :
37 : using rtl::OString;
38 : using rtl::OUString;
39 : using rtl::OUStringBuffer;
40 :
41 : namespace
42 : {
43 : class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
44 : }
45 :
46 : namespace cppu
47 : {
48 :
49 : /** Shared mutex for implementation helper initialization.
50 : Not for public use.
51 : */
52 36276 : ::osl::Mutex & SAL_CALL getImplHelperInitMutex()
53 : {
54 36276 : return theImplHelperInitMutex::get();
55 : }
56 :
57 :
58 1851423663 : static inline void checkInterface( Type const & rType )
59 : {
60 1851423663 : if (TypeClass_INTERFACE != rType.getTypeClass())
61 : {
62 0 : OUString msg( "querying for interface \"" + rType.getTypeName() + "\": no interface type!" );
63 : SAL_WARN( "cppuhelper", msg );
64 0 : throw RuntimeException( msg );
65 : }
66 1851423662 : }
67 :
68 1838061967 : static inline bool isXInterface( rtl_uString * pStr )
69 : {
70 1838061967 : return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
71 : }
72 :
73 1828762770 : static inline void * makeInterface( sal_IntPtr nOffset, void * that )
74 : {
75 1828762770 : return (static_cast<char *>(that) + nOffset);
76 : }
77 :
78 3355650908 : static inline bool __td_equals(
79 : typelib_TypeDescriptionReference const * pTDR1,
80 : typelib_TypeDescriptionReference const * pTDR2 )
81 : {
82 4882621026 : return ((pTDR1 == pTDR2) ||
83 4882621026 : OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
84 : }
85 :
86 1848831333 : static inline type_entry * __getTypeEntries( class_data * cd )
87 : {
88 1848831333 : type_entry * pEntries = cd->m_typeEntries;
89 1848831333 : if (! cd->m_storedTypeRefs) // not inited?
90 : {
91 36276 : MutexGuard guard( getImplHelperInitMutex() );
92 36276 : if (! cd->m_storedTypeRefs) // not inited?
93 : {
94 : // get all types
95 213998 : for ( sal_Int32 n = cd->m_nTypes; n--; )
96 : {
97 141446 : type_entry * pEntry = &pEntries[ n ];
98 141446 : Type const & rType = (*pEntry->m_type.getCppuType)( 0 );
99 : OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
100 : OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
101 141446 : if (rType.getTypeClass() != TypeClass_INTERFACE)
102 : {
103 0 : OUString msg( "type \"" + rType.getTypeName() + "\" is no interface type!" );
104 : SAL_WARN( "cppuhelper", msg );
105 0 : throw RuntimeException( msg );
106 : }
107 : // ref is statically held by getCppuType()
108 141446 : pEntry->m_type.typeRef = rType.getTypeLibType();
109 : }
110 36276 : cd->m_storedTypeRefs = sal_True;
111 36276 : }
112 : }
113 1848831333 : return pEntries;
114 : }
115 :
116 40132 : static inline void __fillTypes( Type * types, class_data * cd )
117 : {
118 40132 : type_entry * pEntries = __getTypeEntries( cd );
119 856758 : for ( sal_Int32 n = cd->m_nTypes; n--; )
120 : {
121 776494 : types[ n ] = pEntries[ n ].m_type.typeRef;
122 : }
123 40132 : }
124 :
125 : namespace {
126 :
127 146289393 : bool recursivelyFindType(
128 : typelib_TypeDescriptionReference const * demandedType,
129 : typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
130 : {
131 : // This code assumes that the vtables of a multiple-inheritance class (the
132 : // offset amount by which to adjust the this pointer) follow one another in
133 : // the object layout, and that they contain slots for the inherited classes
134 : // in a specific order. In theory, that need not hold for any given
135 : // platform; in practice, it seems to work well on all supported platforms:
136 : next:
137 266163901 : for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
138 148290428 : if (i > 0) {
139 2001041 : *offset += sizeof (void *);
140 : }
141 148290428 : typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
142 : // ignore XInterface:
143 148290428 : if (base->nBaseTypes > 0) {
144 31024608 : if (__td_equals(
145 : reinterpret_cast<
146 : typelib_TypeDescriptionReference const * >(base),
147 : demandedType))
148 : {
149 3891383 : return true;
150 : }
151 : // Profiling showed that it is important to speed up the common case
152 : // of only one base:
153 27133289 : if (type->nBaseTypes == 1) {
154 24419303 : type = base;
155 24419303 : goto next;
156 : }
157 2713986 : if (recursivelyFindType(demandedType, base, offset)) {
158 105300 : return true;
159 : }
160 : }
161 : }
162 117873473 : return false;
163 : }
164 :
165 : }
166 :
167 1848791202 : static inline void * __queryDeepNoXInterface(
168 : typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that )
169 : {
170 1848791202 : type_entry * pEntries = __getTypeEntries( cd );
171 1848791061 : sal_Int32 nTypes = cd->m_nTypes;
172 : sal_Int32 n;
173 :
174 : // try top interfaces without getting td
175 3348628036 : for ( n = 0; n < nTypes; ++n )
176 : {
177 3324626306 : if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
178 : {
179 1824789479 : return makeInterface( pEntries[ n ].m_offset, that );
180 : }
181 : }
182 : // query deep getting td
183 139266528 : for ( n = 0; n < nTypes; ++n )
184 : {
185 119156167 : typelib_TypeDescription * pTD = 0;
186 119156167 : TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
187 119156167 : if (pTD)
188 : {
189 : // exclude top (already tested) and bottom (XInterface) interface
190 : OSL_ENSURE(
191 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
192 : nBaseTypes > 0,
193 : "### want to implement XInterface:"
194 : " template argument is XInterface?!?!?!" );
195 119156167 : sal_IntPtr offset = pEntries[n].m_offset;
196 : bool found = recursivelyFindType(
197 : pDemandedTDR,
198 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
199 119156167 : &offset);
200 119156171 : TYPELIB_DANGER_RELEASE( pTD );
201 119156181 : if (found) {
202 3891383 : return makeInterface( offset, that );
203 : }
204 : }
205 : else
206 : {
207 0 : OUString msg( "cannot get type description for type \"" + OUString(pEntries[ n ].m_type.typeRef->pTypeName) + "\"!" );
208 : SAL_WARN( "cppuhelper", msg );
209 0 : throw RuntimeException( msg );
210 : }
211 : }
212 20110361 : return 0;
213 : }
214 :
215 : // ImplHelper
216 :
217 1617942 : Any SAL_CALL ImplHelper_query(
218 : Type const & rType, class_data * cd, void * that )
219 : {
220 1617942 : checkInterface( rType );
221 1617942 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
222 :
223 : void * p;
224 : // shortcut for XInterface
225 1617942 : if (isXInterface( pTDR->pTypeName ))
226 : {
227 : // take first one
228 81912 : p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
229 : }
230 : else
231 : {
232 1536030 : p = __queryDeepNoXInterface( pTDR, cd, that );
233 1536030 : if (! p)
234 : {
235 1271307 : return Any();
236 : }
237 : }
238 346635 : return Any( &p, pTDR );
239 : }
240 :
241 13361693 : Any SAL_CALL ImplHelper_queryNoXInterface(
242 : Type const & rType, class_data * cd, void * that )
243 : {
244 13361693 : checkInterface( rType );
245 13361693 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
246 :
247 13361693 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
248 13361693 : if (p)
249 : {
250 4462943 : return Any( &p, pTDR );
251 : }
252 : else
253 : {
254 8898750 : return Any();
255 : }
256 : }
257 :
258 6 : css::uno::Sequence<sal_Int8> ImplHelper_getImplementationId(
259 : SAL_UNUSED_PARAMETER class_data *)
260 : {
261 6 : return css::uno::Sequence<sal_Int8>();
262 : }
263 :
264 797 : Sequence< Type > SAL_CALL ImplHelper_getTypes(
265 : class_data * cd )
266 : {
267 797 : Sequence< Type > types( cd->m_nTypes );
268 797 : Type * pTypes = types.getArray();
269 797 : __fillTypes( pTypes, cd );
270 797 : return types;
271 : }
272 :
273 1139 : Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
274 : class_data * cd, Sequence< Type > const & rAddTypes )
275 : {
276 1139 : sal_Int32 nImplTypes = cd->m_nTypes;
277 1139 : sal_Int32 nAddTypes = rAddTypes.getLength();
278 1139 : Sequence< Type > types( nImplTypes + nAddTypes );
279 1139 : Type * pTypes = types.getArray();
280 1139 : __fillTypes( pTypes, cd );
281 : // append base types
282 1139 : Type const * pAddTypes = rAddTypes.getConstArray();
283 9305 : while (nAddTypes--)
284 : {
285 7027 : pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
286 : }
287 1139 : return types;
288 : }
289 :
290 : // WeakImplHelper
291 :
292 1357946271 : Any SAL_CALL WeakImplHelper_query(
293 : Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
294 : {
295 1357946271 : checkInterface( rType );
296 1357946261 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
297 :
298 : // shortcut XInterface to OWeakObject
299 1357946258 : if (! isXInterface( pTDR->pTypeName ))
300 : {
301 1356766737 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
302 1356766734 : if (p)
303 : {
304 1347768655 : return Any( &p, pTDR );
305 : }
306 : }
307 10177605 : return pBase->OWeakObject::queryInterface( rType );
308 : }
309 :
310 26490 : Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
311 : class_data * cd )
312 : {
313 26490 : sal_Int32 nTypes = cd->m_nTypes;
314 26490 : Sequence< Type > types( nTypes +1 );
315 26490 : Type * pTypes = types.getArray();
316 26490 : __fillTypes( pTypes, cd );
317 26490 : pTypes[ nTypes ] = cppu::UnoType<XWeak>::get();
318 26490 : return types;
319 : }
320 :
321 : // WeakAggImplHelper
322 :
323 3381572 : Any SAL_CALL WeakAggImplHelper_queryAgg(
324 : Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
325 : {
326 3381572 : checkInterface( rType );
327 3381571 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
328 :
329 : // shortcut XInterface to OWeakAggObject
330 3381572 : if (! isXInterface( pTDR->pTypeName ))
331 : {
332 2231262 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
333 2231263 : if (p)
334 : {
335 1758302 : return Any( &p, pTDR );
336 : }
337 : }
338 1623270 : return pBase->OWeakAggObject::queryAggregation( rType );
339 : }
340 :
341 11264 : Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
342 : class_data * cd )
343 : {
344 11264 : sal_Int32 nTypes = cd->m_nTypes;
345 11264 : Sequence< Type > types( nTypes +2 );
346 11264 : Type * pTypes = types.getArray();
347 11264 : __fillTypes( pTypes, cd );
348 11264 : pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
349 11264 : pTypes[ nTypes ] = cppu::UnoType<XAggregation>::get();
350 11264 : return types;
351 : }
352 :
353 : // WeakComponentImplHelper
354 :
355 475084764 : Any SAL_CALL WeakComponentImplHelper_query(
356 : Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
357 : {
358 475084764 : checkInterface( rType );
359 475084764 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
360 :
361 : // shortcut XInterface to WeakComponentImplHelperBase
362 475084764 : if (! isXInterface( pTDR->pTypeName ))
363 : {
364 474875534 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
365 474875534 : if (p)
366 : {
367 474424840 : return Any( &p, pTDR );
368 : }
369 : }
370 659924 : return pBase->WeakComponentImplHelperBase::queryInterface( rType );
371 : }
372 :
373 286 : Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
374 : class_data * cd )
375 : {
376 286 : sal_Int32 nTypes = cd->m_nTypes;
377 286 : Sequence< Type > types( nTypes +2 );
378 286 : Type * pTypes = types.getArray();
379 286 : __fillTypes( pTypes, cd );
380 286 : pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
381 286 : pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
382 286 : return types;
383 : }
384 :
385 : // WeakAggComponentImplHelper
386 :
387 31440 : Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
388 : Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
389 : {
390 31440 : checkInterface( rType );
391 31440 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
392 :
393 : // shortcut XInterface to WeakAggComponentImplHelperBase
394 31440 : if (! isXInterface( pTDR->pTypeName ))
395 : {
396 19975 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
397 19975 : if (p)
398 : {
399 1404 : return Any( &p, pTDR );
400 : }
401 : }
402 30036 : return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
403 : }
404 :
405 156 : Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
406 : class_data * cd )
407 : {
408 156 : sal_Int32 nTypes = cd->m_nTypes;
409 156 : Sequence< Type > types( nTypes +3 );
410 156 : Type * pTypes = types.getArray();
411 156 : __fillTypes( pTypes, cd );
412 156 : pTypes[ nTypes++ ] = cppu::UnoType<XWeak>::get();
413 156 : pTypes[ nTypes++ ] = cppu::UnoType<XAggregation>::get();
414 156 : pTypes[ nTypes ] = cppu::UnoType<lang::XComponent>::get();
415 156 : return types;
416 : }
417 :
418 : }
419 :
420 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|