1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/diagnose.h>
21 #include <sal/log.hxx>
22 #include <cppuhelper/compbase_ex.hxx>
23 #include <cppuhelper/implbase_ex.hxx>
25 #include <com/sun/star/uno/RuntimeException.hpp>
27 using namespace ::cppu
;
28 using namespace ::osl
;
29 using namespace ::com::sun::star
;
30 using namespace ::com::sun::star::uno
;
34 class theImplHelperInitMutex
: public rtl::Static
<Mutex
, theImplHelperInitMutex
>{};
40 /** Shared mutex for implementation helper initialization.
43 static ::osl::Mutex
& getImplHelperInitMutex()
45 return theImplHelperInitMutex::get();
49 static void checkInterface( Type
const & rType
)
51 if (TypeClass_INTERFACE
!= rType
.getTypeClass())
53 OUString
msg( "querying for interface \"" + rType
.getTypeName() + "\": no interface type!" );
54 SAL_WARN( "cppuhelper", msg
);
55 throw RuntimeException( msg
);
59 static bool isXInterface( rtl_uString
* pStr
)
61 return OUString::unacquired(&pStr
) == "com.sun.star.uno.XInterface";
64 static void * makeInterface( sal_IntPtr nOffset
, void * that
)
66 return (static_cast<char *>(that
) + nOffset
);
69 static bool td_equals(
70 typelib_TypeDescriptionReference
const * pTDR1
,
71 typelib_TypeDescriptionReference
const * pTDR2
)
73 return ((pTDR1
== pTDR2
) ||
74 OUString::unacquired(&pTDR1
->pTypeName
) == OUString::unacquired(&pTDR2
->pTypeName
));
77 static type_entry
* getTypeEntries( class_data
* cd
)
79 type_entry
* pEntries
= cd
->m_typeEntries
;
80 if (! cd
->m_storedTypeRefs
) // not inited?
82 MutexGuard
guard( getImplHelperInitMutex() );
83 if (! cd
->m_storedTypeRefs
) // not inited?
86 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
88 type_entry
* pEntry
= &pEntries
[ n
];
89 Type
const & rType
= (*pEntry
->m_type
.getCppuType
)( nullptr );
90 OSL_ENSURE( rType
.getTypeClass() == TypeClass_INTERFACE
, "### wrong helper init: expected interface!" );
91 OSL_ENSURE( ! isXInterface( rType
.getTypeLibType()->pTypeName
), "### want to implement XInterface: template argument is XInterface?!?!?!" );
92 if (rType
.getTypeClass() != TypeClass_INTERFACE
)
94 OUString
msg( "type \"" + rType
.getTypeName() + "\" is no interface type!" );
95 SAL_WARN( "cppuhelper", msg
);
96 throw RuntimeException( msg
);
98 // ref is statically held by getCppuType()
99 pEntry
->m_type
.typeRef
= rType
.getTypeLibType();
101 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
102 cd
->m_storedTypeRefs
= true;
107 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
112 static void fillTypes( Type
* types
, class_data
* cd
)
114 type_entry
* pEntries
= getTypeEntries( cd
);
115 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
117 types
[ n
] = pEntries
[ n
].m_type
.typeRef
;
123 bool recursivelyFindType(
124 typelib_TypeDescriptionReference
const * demandedType
,
125 typelib_InterfaceTypeDescription
const * type
, sal_IntPtr
* offset
)
127 // This code assumes that the vtables of a multiple-inheritance class (the
128 // offset amount by which to adjust the this pointer) follow one another in
129 // the object layout, and that they contain slots for the inherited classes
130 // in a specific order. In theory, that need not hold for any given
131 // platform; in practice, it seems to work well on all supported platforms:
133 for (sal_Int32 i
= 0; i
< type
->nBaseTypes
; ++i
) {
135 *offset
+= sizeof (void *);
137 typelib_InterfaceTypeDescription
const * base
= type
->ppBaseTypes
[i
];
138 // ignore XInterface:
139 if (base
->nBaseTypes
> 0) {
142 typelib_TypeDescriptionReference
const * >(base
),
147 // Profiling showed that it is important to speed up the common case
149 if (type
->nBaseTypes
== 1) {
153 if (recursivelyFindType(demandedType
, base
, offset
)) {
163 static void * queryDeepNoXInterface(
164 typelib_TypeDescriptionReference
const * pDemandedTDR
, class_data
* cd
, void * that
)
166 type_entry
* pEntries
= getTypeEntries( cd
);
167 sal_Int32 nTypes
= cd
->m_nTypes
;
170 // try top interfaces without getting td
171 for ( n
= 0; n
< nTypes
; ++n
)
173 if (td_equals( pEntries
[ n
].m_type
.typeRef
, pDemandedTDR
))
175 return makeInterface( pEntries
[ n
].m_offset
, that
);
178 // query deep getting td
179 for ( n
= 0; n
< nTypes
; ++n
)
181 typelib_TypeDescription
* pTD
= nullptr;
182 TYPELIB_DANGER_GET( &pTD
, pEntries
[ n
].m_type
.typeRef
);
185 // exclude top (already tested) and bottom (XInterface) interface
187 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
)->
189 "### want to implement XInterface:"
190 " template argument is XInterface?!?!?!" );
191 sal_IntPtr offset
= pEntries
[n
].m_offset
;
192 bool found
= recursivelyFindType(
194 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
),
196 TYPELIB_DANGER_RELEASE( pTD
);
198 return makeInterface( offset
, that
);
203 OUString
msg( "cannot get type description for type \"" + OUString::unacquired(&pEntries
[ n
].m_type
.typeRef
->pTypeName
) + "\"!" );
204 SAL_WARN( "cppuhelper", msg
);
205 throw RuntimeException( msg
);
213 Any SAL_CALL
ImplHelper_query(
214 Type
const & rType
, class_data
* cd
, void * that
)
216 checkInterface( rType
);
217 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
220 // shortcut for XInterface
221 if (isXInterface( pTDR
->pTypeName
))
224 p
= makeInterface( cd
->m_typeEntries
[ 0 ].m_offset
, that
);
228 p
= queryDeepNoXInterface( pTDR
, cd
, that
);
234 return Any( &p
, pTDR
);
237 Any SAL_CALL
ImplHelper_queryNoXInterface(
238 Type
const & rType
, class_data
* cd
, void * that
)
240 checkInterface( rType
);
241 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
243 void * p
= queryDeepNoXInterface( pTDR
, cd
, that
);
246 return Any( &p
, pTDR
);
251 css::uno::Sequence
<sal_Int8
> ImplHelper_getImplementationId(
252 SAL_UNUSED_PARAMETER class_data
*)
254 return css::uno::Sequence
<sal_Int8
>();
257 Sequence
< Type
> SAL_CALL
ImplHelper_getTypes(
260 Sequence
< Type
> types( cd
->m_nTypes
);
261 Type
* pTypes
= types
.getArray();
262 fillTypes( pTypes
, cd
);
266 Sequence
< Type
> SAL_CALL
ImplInhHelper_getTypes(
267 class_data
* cd
, Sequence
< Type
> const & rAddTypes
)
269 sal_Int32 nImplTypes
= cd
->m_nTypes
;
270 sal_Int32 nAddTypes
= rAddTypes
.getLength();
271 Sequence
< Type
> types( nImplTypes
+ nAddTypes
);
272 Type
* pTypes
= types
.getArray();
273 fillTypes( pTypes
, cd
);
275 Type
const * pAddTypes
= rAddTypes
.getConstArray();
278 pTypes
[ nImplTypes
+ nAddTypes
] = pAddTypes
[ nAddTypes
];
285 Any SAL_CALL
WeakImplHelper_query(
286 Type
const & rType
, class_data
* cd
, void * that
, OWeakObject
* pBase
)
288 checkInterface( rType
);
289 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
291 // shortcut XInterface to OWeakObject
292 if (! isXInterface( pTDR
->pTypeName
))
294 void * p
= queryDeepNoXInterface( pTDR
, cd
, that
);
297 return Any( &p
, pTDR
);
300 return pBase
->OWeakObject::queryInterface( rType
);
303 Sequence
< Type
> SAL_CALL
WeakImplHelper_getTypes(
306 sal_Int32 nTypes
= cd
->m_nTypes
;
307 Sequence
< Type
> types( nTypes
+1 );
308 Type
* pTypes
= types
.getArray();
309 fillTypes( pTypes
, cd
);
310 pTypes
[ nTypes
] = cppu::UnoType
<XWeak
>::get();
316 Any SAL_CALL
WeakAggImplHelper_queryAgg(
317 Type
const & rType
, class_data
* cd
, void * that
, OWeakAggObject
* pBase
)
319 checkInterface( rType
);
320 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
322 // shortcut XInterface to OWeakAggObject
323 if (! isXInterface( pTDR
->pTypeName
))
325 void * p
= queryDeepNoXInterface( pTDR
, cd
, that
);
328 return Any( &p
, pTDR
);
331 return pBase
->OWeakAggObject::queryAggregation( rType
);
334 Sequence
< Type
> SAL_CALL
WeakAggImplHelper_getTypes(
337 sal_Int32 nTypes
= cd
->m_nTypes
;
338 Sequence
< Type
> types( nTypes
+2 );
339 Type
* pTypes
= types
.getArray();
340 fillTypes( pTypes
, cd
);
341 pTypes
[ nTypes
++ ] = cppu::UnoType
<XWeak
>::get();
342 pTypes
[ nTypes
] = cppu::UnoType
<XAggregation
>::get();
346 // WeakComponentImplHelper
348 Any SAL_CALL
WeakComponentImplHelper_query(
349 Type
const & rType
, class_data
* cd
, void * that
, WeakComponentImplHelperBase
* pBase
)
351 checkInterface( rType
);
352 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
354 // shortcut XInterface to WeakComponentImplHelperBase
355 if (! isXInterface( pTDR
->pTypeName
))
357 void * p
= queryDeepNoXInterface( pTDR
, cd
, that
);
360 return Any( &p
, pTDR
);
363 return pBase
->WeakComponentImplHelperBase::queryInterface( rType
);
366 Sequence
< Type
> SAL_CALL
WeakComponentImplHelper_getTypes(
369 sal_Int32 nTypes
= cd
->m_nTypes
;
370 Sequence
< Type
> types( nTypes
+2 );
371 Type
* pTypes
= types
.getArray();
372 fillTypes( pTypes
, cd
);
373 pTypes
[ nTypes
++ ] = cppu::UnoType
<XWeak
>::get();
374 pTypes
[ nTypes
] = cppu::UnoType
<lang::XComponent
>::get();
378 // WeakAggComponentImplHelper
380 Any SAL_CALL
WeakAggComponentImplHelper_queryAgg(
381 Type
const & rType
, class_data
* cd
, void * that
, WeakAggComponentImplHelperBase
* pBase
)
383 checkInterface( rType
);
384 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
386 // shortcut XInterface to WeakAggComponentImplHelperBase
387 if (! isXInterface( pTDR
->pTypeName
))
389 void * p
= queryDeepNoXInterface( pTDR
, cd
, that
);
392 return Any( &p
, pTDR
);
395 return pBase
->WeakAggComponentImplHelperBase::queryAggregation( rType
);
398 Sequence
< Type
> SAL_CALL
WeakAggComponentImplHelper_getTypes(
401 sal_Int32 nTypes
= cd
->m_nTypes
;
402 Sequence
< Type
> types( nTypes
+3 );
403 Type
* pTypes
= types
.getArray();
404 fillTypes( pTypes
, cd
);
405 pTypes
[ nTypes
++ ] = cppu::UnoType
<XWeak
>::get();
406 pTypes
[ nTypes
++ ] = cppu::UnoType
<XAggregation
>::get();
407 pTypes
[ nTypes
] = cppu::UnoType
<lang::XComponent
>::get();
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */