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 <sal/alloca.h>
23 #include <osl/diagnose.h>
24 #include <rtl/byteseq.hxx>
25 #include <rtl/ustrbuf.hxx>
27 #include <cppuhelper/compbase_ex.hxx>
29 #include "com/sun/star/uno/RuntimeException.hpp"
31 using namespace ::cppu
;
32 using namespace ::osl
;
33 using namespace ::com::sun::star
;
34 using namespace ::com::sun::star::uno
;
38 using rtl::OUStringBuffer
;
43 /** Shared mutex for implementation helper initialization.
46 ::osl::Mutex
& SAL_CALL
getImplHelperInitMutex(void) SAL_THROW(());
49 static inline void checkInterface( Type
const & rType
)
50 SAL_THROW( (RuntimeException
) )
52 if (TypeClass_INTERFACE
!= rType
.getTypeClass())
54 OUString
msg( "querying for interface \"" + rType
.getTypeName() + "\": no interface type!" );
55 SAL_WARN( "cppuhelper", msg
);
56 throw RuntimeException( msg
, Reference
< XInterface
>() );
60 static inline bool isXInterface( rtl_uString
* pStr
) SAL_THROW(())
62 return (*((OUString
const *)&pStr
) == "com.sun.star.uno.XInterface");
65 static inline void * makeInterface( sal_IntPtr nOffset
, void * that
) SAL_THROW(())
67 return (((char *)that
) + nOffset
);
70 static inline bool __td_equals(
71 typelib_TypeDescriptionReference
const * pTDR1
,
72 typelib_TypeDescriptionReference
const * pTDR2
)
75 return ((pTDR1
== pTDR2
) ||
76 ((OUString
const *)&pTDR1
->pTypeName
)->equals( *(OUString
const *)&pTDR2
->pTypeName
));
79 static inline type_entry
* __getTypeEntries( class_data
* cd
)
80 SAL_THROW( (RuntimeException
) )
82 type_entry
* pEntries
= cd
->m_typeEntries
;
83 if (! cd
->m_storedTypeRefs
) // not inited?
85 MutexGuard
guard( getImplHelperInitMutex() );
86 if (! cd
->m_storedTypeRefs
) // not inited?
89 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
91 type_entry
* pEntry
= &pEntries
[ n
];
92 Type
const & rType
= (*pEntry
->m_type
.getCppuType
)( 0 );
93 OSL_ENSURE( rType
.getTypeClass() == TypeClass_INTERFACE
, "### wrong helper init: expected interface!" );
94 OSL_ENSURE( ! isXInterface( rType
.getTypeLibType()->pTypeName
), "### want to implement XInterface: template argument is XInterface?!?!?!" );
95 if (rType
.getTypeClass() != TypeClass_INTERFACE
)
97 OUString
msg( "type \"" + rType
.getTypeName() + "\" is no interface type!" );
98 SAL_WARN( "cppuhelper", msg
);
99 throw RuntimeException( msg
, Reference
< XInterface
>() );
101 // ref is statically held by getCppuType()
102 pEntry
->m_type
.typeRef
= rType
.getTypeLibType();
104 cd
->m_storedTypeRefs
= sal_True
;
110 static inline void __fillTypes( Type
* types
, class_data
* cd
)
111 SAL_THROW( (RuntimeException
) )
113 type_entry
* pEntries
= __getTypeEntries( cd
);
114 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
116 types
[ n
] = pEntries
[ n
].m_type
.typeRef
;
122 bool recursivelyFindType(
123 typelib_TypeDescriptionReference
const * demandedType
,
124 typelib_InterfaceTypeDescription
const * type
, sal_IntPtr
* offset
)
126 // This code assumes that the vtables of a multiple-inheritance class (the
127 // offset amount by which to adjust the this pointer) follow one another in
128 // the object layout, and that they contain slots for the inherited classes
129 // in a specific order. In theory, that need not hold for any given
130 // platform; in practice, it seems to work well on all supported platforms:
132 for (sal_Int32 i
= 0; i
< type
->nBaseTypes
; ++i
) {
134 *offset
+= sizeof (void *);
136 typelib_InterfaceTypeDescription
const * base
= type
->ppBaseTypes
[i
];
137 // ignore XInterface:
138 if (base
->nBaseTypes
> 0) {
141 typelib_TypeDescriptionReference
const * >(base
),
146 // Profiling showed that it is important to speed up the common case
148 if (type
->nBaseTypes
== 1) {
152 if (recursivelyFindType(demandedType
, base
, offset
)) {
162 static inline void * __queryDeepNoXInterface(
163 typelib_TypeDescriptionReference
* pDemandedTDR
, class_data
* cd
, void * that
)
164 SAL_THROW( (RuntimeException
) )
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
= 0;
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(pEntries
[ n
].m_type
.typeRef
->pTypeName
) + "\"!" );
204 SAL_WARN( "cppuhelper", msg
);
205 throw RuntimeException( msg
, Reference
< XInterface
>() );
213 Any SAL_CALL
ImplHelper_query(
214 Type
const & rType
, class_data
* cd
, void * that
)
215 SAL_THROW( (RuntimeException
) )
217 checkInterface( rType
);
218 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
221 // shortcut for XInterface
222 if (isXInterface( pTDR
->pTypeName
))
225 p
= makeInterface( cd
->m_typeEntries
[ 0 ].m_offset
, that
);
229 p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
235 return Any( &p
, pTDR
);
238 Any SAL_CALL
ImplHelper_queryNoXInterface(
239 Type
const & rType
, class_data
* cd
, void * that
)
240 SAL_THROW( (RuntimeException
) )
242 checkInterface( rType
);
243 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
245 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
248 return Any( &p
, pTDR
);
256 css::uno::Sequence
<sal_Int8
> ImplHelper_getImplementationId(
257 SAL_UNUSED_PARAMETER class_data
*) SAL_THROW((css::uno::RuntimeException
))
259 return css::uno::Sequence
<sal_Int8
>();
262 Sequence
< Type
> SAL_CALL
ImplHelper_getTypes(
264 SAL_THROW( (RuntimeException
) )
266 Sequence
< Type
> types( cd
->m_nTypes
);
267 Type
* pTypes
= types
.getArray();
268 __fillTypes( pTypes
, cd
);
272 Sequence
< Type
> SAL_CALL
ImplInhHelper_getTypes(
273 class_data
* cd
, Sequence
< Type
> const & rAddTypes
)
274 SAL_THROW( (RuntimeException
) )
276 sal_Int32 nImplTypes
= cd
->m_nTypes
;
277 sal_Int32 nAddTypes
= rAddTypes
.getLength();
278 Sequence
< Type
> types( nImplTypes
+ nAddTypes
);
279 Type
* pTypes
= types
.getArray();
280 __fillTypes( pTypes
, cd
);
282 Type
const * pAddTypes
= rAddTypes
.getConstArray();
285 pTypes
[ nImplTypes
+ nAddTypes
] = pAddTypes
[ nAddTypes
];
292 Any SAL_CALL
WeakImplHelper_query(
293 Type
const & rType
, class_data
* cd
, void * that
, OWeakObject
* pBase
)
294 SAL_THROW( (RuntimeException
) )
296 checkInterface( rType
);
297 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
299 // shortcut XInterface to OWeakObject
300 if (! isXInterface( pTDR
->pTypeName
))
302 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
305 return Any( &p
, pTDR
);
308 return pBase
->OWeakObject::queryInterface( rType
);
311 Sequence
< Type
> SAL_CALL
WeakImplHelper_getTypes(
313 SAL_THROW( (RuntimeException
) )
315 sal_Int32 nTypes
= cd
->m_nTypes
;
316 Sequence
< Type
> types( nTypes
+1 );
317 Type
* pTypes
= types
.getArray();
318 __fillTypes( pTypes
, cd
);
319 pTypes
[ nTypes
] = ::getCppuType( (Reference
< XWeak
> const *)0 );
325 Any SAL_CALL
WeakAggImplHelper_queryAgg(
326 Type
const & rType
, class_data
* cd
, void * that
, OWeakAggObject
* pBase
)
327 SAL_THROW( (RuntimeException
) )
329 checkInterface( rType
);
330 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
332 // shortcut XInterface to OWeakAggObject
333 if (! isXInterface( pTDR
->pTypeName
))
335 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
338 return Any( &p
, pTDR
);
341 return pBase
->OWeakAggObject::queryAggregation( rType
);
344 Sequence
< Type
> SAL_CALL
WeakAggImplHelper_getTypes(
346 SAL_THROW( (RuntimeException
) )
348 sal_Int32 nTypes
= cd
->m_nTypes
;
349 Sequence
< Type
> types( nTypes
+2 );
350 Type
* pTypes
= types
.getArray();
351 __fillTypes( pTypes
, cd
);
352 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
353 pTypes
[ nTypes
] = ::getCppuType( (const Reference
< XAggregation
> *)0 );
357 // WeakComponentImplHelper
359 Any SAL_CALL
WeakComponentImplHelper_query(
360 Type
const & rType
, class_data
* cd
, void * that
, WeakComponentImplHelperBase
* pBase
)
361 SAL_THROW( (RuntimeException
) )
363 checkInterface( rType
);
364 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
366 // shortcut XInterface to WeakComponentImplHelperBase
367 if (! isXInterface( pTDR
->pTypeName
))
369 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
372 return Any( &p
, pTDR
);
375 return pBase
->WeakComponentImplHelperBase::queryInterface( rType
);
378 Sequence
< Type
> SAL_CALL
WeakComponentImplHelper_getTypes(
380 SAL_THROW( (RuntimeException
) )
382 sal_Int32 nTypes
= cd
->m_nTypes
;
383 Sequence
< Type
> types( nTypes
+2 );
384 Type
* pTypes
= types
.getArray();
385 __fillTypes( pTypes
, cd
);
386 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
387 pTypes
[ nTypes
] = ::getCppuType( (Reference
< lang::XComponent
> const *)0 );
391 // WeakAggComponentImplHelper
393 Any SAL_CALL
WeakAggComponentImplHelper_queryAgg(
394 Type
const & rType
, class_data
* cd
, void * that
, WeakAggComponentImplHelperBase
* pBase
)
395 SAL_THROW( (RuntimeException
) )
397 checkInterface( rType
);
398 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
400 // shortcut XInterface to WeakAggComponentImplHelperBase
401 if (! isXInterface( pTDR
->pTypeName
))
403 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
406 return Any( &p
, pTDR
);
409 return pBase
->WeakAggComponentImplHelperBase::queryAggregation( rType
);
412 Sequence
< Type
> SAL_CALL
WeakAggComponentImplHelper_getTypes(
414 SAL_THROW( (RuntimeException
) )
416 sal_Int32 nTypes
= cd
->m_nTypes
;
417 Sequence
< Type
> types( nTypes
+3 );
418 Type
* pTypes
= types
.getArray();
419 __fillTypes( pTypes
, cd
);
420 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
421 pTypes
[ nTypes
++ ] = ::getCppuType( (const Reference
< XAggregation
> *)0 );
422 pTypes
[ nTypes
] = ::getCppuType( (const Reference
< lang::XComponent
> *)0 );
428 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */