Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / cppuhelper / source / implbase_ex.cxx
blob00eeaf3766189f36b841bb259c34aca2f2addadb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
32 namespace
34 class theImplHelperInitMutex : public rtl::Static<Mutex, theImplHelperInitMutex>{};
37 namespace cppu
40 /** Shared mutex for implementation helper initialization.
41 Not for public use.
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?
85 // get all types
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;
105 else
107 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
109 return pEntries;
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;
121 namespace {
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:
132 next:
133 for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
134 if (i > 0) {
135 *offset += sizeof (void *);
137 typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
138 // ignore XInterface:
139 if (base->nBaseTypes > 0) {
140 if (td_equals(
141 reinterpret_cast<
142 typelib_TypeDescriptionReference const * >(base),
143 demandedType))
145 return true;
147 // Profiling showed that it is important to speed up the common case
148 // of only one base:
149 if (type->nBaseTypes == 1) {
150 type = base;
151 goto next;
153 if (recursivelyFindType(demandedType, base, offset)) {
154 return true;
158 return false;
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;
168 sal_Int32 n;
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 );
183 if (pTD)
185 // exclude top (already tested) and bottom (XInterface) interface
186 OSL_ENSURE(
187 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
188 nBaseTypes > 0,
189 "### want to implement XInterface:"
190 " template argument is XInterface?!?!?!" );
191 sal_IntPtr offset = pEntries[n].m_offset;
192 bool found = recursivelyFindType(
193 pDemandedTDR,
194 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
195 &offset);
196 TYPELIB_DANGER_RELEASE( pTD );
197 if (found) {
198 return makeInterface( offset, that );
201 else
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 );
208 return nullptr;
211 // ImplHelper
213 Any SAL_CALL ImplHelper_query(
214 Type const & rType, class_data * cd, void * that )
216 checkInterface( rType );
217 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
219 void * p;
220 // shortcut for XInterface
221 if (isXInterface( pTDR->pTypeName ))
223 // take first one
224 p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
226 else
228 p = queryDeepNoXInterface( pTDR, cd, that );
229 if (! p)
231 return Any();
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 );
244 if (p)
246 return Any( &p, pTDR );
248 return Any();
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(
258 class_data * cd )
260 Sequence< Type > types( cd->m_nTypes );
261 Type * pTypes = types.getArray();
262 fillTypes( pTypes, cd );
263 return types;
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 );
274 // append base types
275 Type const * pAddTypes = rAddTypes.getConstArray();
276 while (nAddTypes--)
278 pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
280 return types;
283 // WeakImplHelper
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 );
295 if (p)
297 return Any( &p, pTDR );
300 return pBase->OWeakObject::queryInterface( rType );
303 Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
304 class_data * cd )
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();
311 return types;
314 // WeakAggImplHelper
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 );
326 if (p)
328 return Any( &p, pTDR );
331 return pBase->OWeakAggObject::queryAggregation( rType );
334 Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
335 class_data * cd )
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();
343 return types;
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 );
358 if (p)
360 return Any( &p, pTDR );
363 return pBase->WeakComponentImplHelperBase::queryInterface( rType );
366 Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
367 class_data * cd )
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();
375 return types;
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 );
390 if (p)
392 return Any( &p, pTDR );
395 return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
398 Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
399 class_data * cd )
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();
408 return types;
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */