LCOV - code coverage report
Current view: top level - cppuhelper/source - implbase_ex.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 157 163 96.3 %
Date: 2015-06-13 12:38:46 Functions: 22 22 100.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.11