blob: 1a9b0a83df9b5f4f56cb4a7ed076f77422fc33b9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppu.hxx"
#include <hash_map>
#include <list>
#include <set>
#include <vector>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sal/alloca.h>
#include <new>
#include <osl/interlck.h>
#include <osl/mutex.hxx>
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/alloc.h>
#include <rtl/instance.hxx>
#include <osl/diagnose.h>
#include <typelib/typedescription.h>
#include <uno/any2.h>
using namespace rtl;
using namespace std;
using namespace osl;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
#ifdef SAL_W32
#pragma pack(push, 8)
#elif defined(SAL_OS2)
#pragma pack(8)
#endif
/**
* The double member determin the alignment.
* Under Os2 and MS-Windows the Alignment is min( 8, sizeof( type ) ).
* The aligment of a strukture is min( 8, sizeof( max basic type ) ), the greatest basic type
* determine the aligment.
*/
struct AlignSize_Impl
{
sal_Int16 nInt16;
double dDouble;
};
#ifdef SAL_W32
#pragma pack(pop)
#elif defined(SAL_OS2)
#pragma pack()
#endif
// the value of the maximal alignment
static sal_Int32 nMaxAlignment = (sal_Int32)( (sal_Size)(&((AlignSize_Impl *) 16)->dDouble) - 16);
static inline sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment )
SAL_THROW( () )
{
if( nRequestedAlignment > nMaxAlignment )
nRequestedAlignment = nMaxAlignment;
return nRequestedAlignment;
}
/**
* Calculate the new size of the struktur.
*/
static inline sal_Int32 newAlignedSize(
sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment )
SAL_THROW( () )
{
NeededAlignment = adjustAlignment( NeededAlignment );
return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize;
}
static inline sal_Bool reallyWeak( typelib_TypeClass eTypeClass )
SAL_THROW( () )
{
return TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass );
}
static inline sal_Int32 getDescriptionSize( typelib_TypeClass eTypeClass )
SAL_THROW( () )
{
OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass );
sal_Int32 nSize;
// The reference is the description
// if the description is empty, than it must be filled with
// the new description
switch( eTypeClass )
{
case typelib_TypeClass_ARRAY:
nSize = (sal_Int32)sizeof( typelib_ArrayTypeDescription );
break;
case typelib_TypeClass_SEQUENCE:
nSize = (sal_Int32)sizeof( typelib_IndirectTypeDescription );
break;
case typelib_TypeClass_UNION:
nSize = (sal_Int32)sizeof( typelib_UnionTypeDescription );
break;
case typelib_TypeClass_STRUCT:
nSize = (sal_Int32)sizeof( typelib_StructTypeDescription );
break;
case typelib_TypeClass_EXCEPTION:
nSize = (sal_Int32)sizeof( typelib_CompoundTypeDescription );
break;
case typelib_TypeClass_ENUM:
nSize = (sal_Int32)sizeof( typelib_EnumTypeDescription );
break;
case typelib_TypeClass_INTERFACE:
nSize = (sal_Int32)sizeof( typelib_InterfaceTypeDescription );
break;
case typelib_TypeClass_INTERFACE_METHOD:
nSize = (sal_Int32)sizeof( typelib_InterfaceMethodTypeDescription );
break;
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
nSize = (sal_Int32)sizeof( typelib_InterfaceAttributeTypeDescription );
break;
default:
nSize = (sal_Int32)sizeof( typelib_TypeDescription );
}
return nSize;
}
//-----------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_getByName(
typelib_TypeDescriptionReference ** ppRet, rtl_uString * pName )
SAL_THROW_EXTERN_C();
//-----------------------------------------------------------------------------
struct equalStr_Impl
{
sal_Bool operator()(const sal_Unicode * const & s1, const sal_Unicode * const & s2) const SAL_THROW( () )
{ return 0 == rtl_ustr_compare( s1, s2 ); }
};
//-----------------------------------------------------------------------------
struct hashStr_Impl
{
size_t operator()(const sal_Unicode * const & s) const SAL_THROW( () )
{ return rtl_ustr_hashCode( s ); }
};
//-----------------------------------------------------------------------------
// Heavy hack, the const sal_Unicode * is hold by the typedescription reference
typedef hash_map< const sal_Unicode *, typelib_TypeDescriptionReference *,
hashStr_Impl, equalStr_Impl > WeakMap_Impl;
typedef pair< void *, typelib_typedescription_Callback > CallbackEntry;
typedef list< CallbackEntry > CallbackSet_Impl;
typedef list< typelib_TypeDescription * > TypeDescriptionList_Impl;
// # of cached elements
static sal_Int32 nCacheSize = 256;
//-----------------------------------------------------------------------------
/**
* All members must set initial to 0 and no constructor is needed. So it
* doesn't care, when this class is static initialized.<BR>
*/
struct TypeDescriptor_Init_Impl
{
//sal_Bool bDesctructorCalled;
// all type description references
WeakMap_Impl * pWeakMap;
// all type description callbacks
CallbackSet_Impl * pCallbacks;
// A cache to hold descriptions
TypeDescriptionList_Impl * pCache;
// The mutex to guard all type library accesses
Mutex * pMutex;
inline Mutex & getMutex() SAL_THROW( () );
inline void callChain( typelib_TypeDescription ** ppRet, rtl_uString * pName ) SAL_THROW( () );
#if OSL_DEBUG_LEVEL > 1
// only for debugging
sal_Int32 nTypeDescriptionCount;
sal_Int32 nCompoundTypeDescriptionCount;
sal_Int32 nUnionTypeDescriptionCount;
sal_Int32 nIndirectTypeDescriptionCount;
sal_Int32 nArrayTypeDescriptionCount;
sal_Int32 nEnumTypeDescriptionCount;
sal_Int32 nInterfaceMethodTypeDescriptionCount;
sal_Int32 nInterfaceAttributeTypeDescriptionCount;
sal_Int32 nInterfaceTypeDescriptionCount;
sal_Int32 nTypeDescriptionReferenceCount;
#endif
~TypeDescriptor_Init_Impl() SAL_THROW( () );
};
//__________________________________________________________________________________________________
inline Mutex & TypeDescriptor_Init_Impl::getMutex() SAL_THROW( () )
{
if( !pMutex )
{
MutexGuard aGuard( Mutex::getGlobalMutex() );
if( !pMutex )
pMutex = new Mutex();
}
return * pMutex;
}
//__________________________________________________________________________________________________
inline void TypeDescriptor_Init_Impl::callChain(
typelib_TypeDescription ** ppRet, rtl_uString * pName )
SAL_THROW( () )
{
if (pCallbacks)
{
CallbackSet_Impl::const_iterator aIt = pCallbacks->begin();
while( aIt != pCallbacks->end() )
{
const CallbackEntry & rEntry = *aIt;
(*rEntry.second)( rEntry.first, ppRet, pName );
if( *ppRet )
return;
++aIt;
}
}
if (*ppRet)
{
typelib_typedescription_release( *ppRet );
*ppRet = 0;
}
}
//__________________________________________________________________________________________________
TypeDescriptor_Init_Impl::~TypeDescriptor_Init_Impl() SAL_THROW( () )
{
if( pCache )
{
TypeDescriptionList_Impl::const_iterator aIt = pCache->begin();
while( aIt != pCache->end() )
{
typelib_typedescription_release( (*aIt) );
aIt++;
}
delete pCache;
pCache = 0;
}
if( pWeakMap )
{
sal_Int32 nSize = pWeakMap->size();
typelib_TypeDescriptionReference ** ppTDR = new typelib_TypeDescriptionReference *[ nSize ];
// save al weak references
WeakMap_Impl::const_iterator aIt = pWeakMap->begin();
sal_Int32 i = 0;
while( aIt != pWeakMap->end() )
{
typelib_typedescriptionreference_acquire( ppTDR[i++] = (*aIt).second );
++aIt;
}
for( i = 0; i < nSize; i++ )
{
typelib_TypeDescriptionReference * pTDR = ppTDR[i];
OSL_ASSERT( pTDR->nRefCount > pTDR->nStaticRefCount );
pTDR->nRefCount -= pTDR->nStaticRefCount;
if( pTDR->pType && !pTDR->pType->bOnDemand )
{
pTDR->pType->bOnDemand = sal_True;
typelib_typedescription_release( pTDR->pType );
}
typelib_typedescriptionreference_release( pTDR );
}
delete [] ppTDR;
#if OSL_DEBUG_LEVEL > 1
aIt = pWeakMap->begin();
while( aIt != pWeakMap->end() )
{
typelib_TypeDescriptionReference * pTDR = (*aIt).second;
if (pTDR)
{
OString aTypeName( OUStringToOString( pTDR->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
OSL_TRACE(
"### remaining type: %s; ref count = %d", aTypeName.getStr(), pTDR->nRefCount );
}
else
{
OSL_TRACE( "### remaining null type entry!?" );
}
++aIt;
}
#endif
delete pWeakMap;
pWeakMap = 0;
}
delete pCallbacks;
pCallbacks = 0;
if( pMutex )
{
delete pMutex;
pMutex = 0;
}
};
namespace { struct Init : public rtl::Static< TypeDescriptor_Init_Impl, Init > {}; }
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_registerCallback(
void * pContext, typelib_typedescription_Callback pCallback )
SAL_THROW_EXTERN_C()
{
// todo mt safe: guard is no solution, can not acquire while calling callback!
TypeDescriptor_Init_Impl &rInit = Init::get();
// OslGuard aGuard( rInit.getMutex() );
if( !rInit.pCallbacks )
rInit.pCallbacks = new CallbackSet_Impl;
rInit.pCallbacks->push_back( CallbackEntry( pContext, pCallback ) );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_revokeCallback(
void * pContext, typelib_typedescription_Callback pCallback )
SAL_THROW_EXTERN_C()
{
TypeDescriptor_Init_Impl &rInit = Init::get();
if( rInit.pCallbacks )
{
// todo mt safe: guard is no solution, can not acquire while calling callback!
// OslGuard aGuard( rInit.getMutex() );
CallbackEntry aEntry( pContext, pCallback );
CallbackSet_Impl::iterator iPos( rInit.pCallbacks->begin() );
while (!(iPos == rInit.pCallbacks->end()))
{
if (*iPos == aEntry)
{
rInit.pCallbacks->erase( iPos );
iPos = rInit.pCallbacks->begin();
}
else
{
++iPos;
}
}
}
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
extern "C" sal_Int32 SAL_CALL typelib_typedescription_getAlignedUnoSize(
const typelib_TypeDescription * pTypeDescription,
sal_Int32 nOffset, sal_Int32 & rMaxIntegralTypeSize )
SAL_THROW_EXTERN_C();
//------------------------------------------------------------------------
static inline void typelib_typedescription_initTables(
typelib_TypeDescription * pTD )
SAL_THROW( () )
{
typelib_InterfaceTypeDescription * pITD = (typelib_InterfaceTypeDescription *)pTD;
sal_Bool * pReadWriteAttributes = (sal_Bool *)alloca( pITD->nAllMembers );
for ( sal_Int32 i = pITD->nAllMembers; i--; )
{
pReadWriteAttributes[i] = sal_False;
if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pITD->ppAllMembers[i]->eTypeClass )
{
typelib_TypeDescription * pM = 0;
TYPELIB_DANGER_GET( &pM, pITD->ppAllMembers[i] );
OSL_ASSERT( pM );
if (pM)
{
pReadWriteAttributes[i] = !((typelib_InterfaceAttributeTypeDescription *)pM)->bReadOnly;
TYPELIB_DANGER_RELEASE( pM );
}
#if OSL_DEBUG_LEVEL > 1
else
{
OString aStr( OUStringToOString( pITD->ppAllMembers[i]->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
OSL_TRACE( "\n### cannot get attribute type description: %s", aStr.getStr() );
}
#endif
}
}
MutexGuard aGuard( Init::get().getMutex() );
if( !pTD->bComplete )
{
// create the index table from member to function table
pITD->pMapMemberIndexToFunctionIndex = new sal_Int32[ pITD->nAllMembers ];
sal_Int32 nAdditionalOffset = 0; // +1 for read/write attributes
sal_Int32 i;
for( i = 0; i < pITD->nAllMembers; i++ )
{
// index to the get method of the attribute
pITD->pMapMemberIndexToFunctionIndex[i] = i + nAdditionalOffset;
// extra offset if it is a read/write attribute?
if( pReadWriteAttributes[i] )
{
// a read/write attribute
nAdditionalOffset++;
}
}
// create the index table from function to member table
pITD->pMapFunctionIndexToMemberIndex = new sal_Int32[ pITD->nAllMembers + nAdditionalOffset ];
nAdditionalOffset = 0; // +1 for read/write attributes
for( i = 0; i < pITD->nAllMembers; i++ )
{
// index to the get method of the attribute
pITD->pMapFunctionIndexToMemberIndex[i + nAdditionalOffset] = i;
// extra offset if it is a read/write attribute?
if( pReadWriteAttributes[i] )
{
// a read/write attribute
pITD->pMapFunctionIndexToMemberIndex[i + ++nAdditionalOffset] = i;
}
}
// must be the last action after all initialization is done
pITD->nMapFunctionIndexToMemberIndex = pITD->nAllMembers + nAdditionalOffset;
pTD->bComplete = sal_True;
}
}
namespace {
// In some situations (notably typelib_typedescription_newInterfaceMethod and
// typelib_typedescription_newInterfaceAttribute), only the members nMembers,
// ppMembers, nAllMembers, and ppAllMembers of an incomplete interface type
// description are necessary, but not the additional
// pMapMemberIndexToFunctionIndex, nMapFunctionIndexToMemberIndex, and
// pMapFunctionIndexToMemberIndex (which are computed by
// typelib_typedescription_initTables). Furthermore, in those situations, it
// might be illegal to compute those tables, as the creation of the interface
// member type descriptions would recursively require a complete interface type
// description. The parameter initTables controls whether or not to call
// typelib_typedescription_initTables in those situations.
bool complete(typelib_TypeDescription ** ppTypeDescr, bool initTables) {
if (! (*ppTypeDescr)->bComplete)
{
OSL_ASSERT( (typelib_TypeClass_STRUCT == (*ppTypeDescr)->eTypeClass ||
typelib_TypeClass_EXCEPTION == (*ppTypeDescr)->eTypeClass ||
typelib_TypeClass_UNION == (*ppTypeDescr)->eTypeClass ||
typelib_TypeClass_ENUM == (*ppTypeDescr)->eTypeClass ||
typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass) &&
!reallyWeak( (*ppTypeDescr)->eTypeClass ) );
if (typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass &&
((typelib_InterfaceTypeDescription *)*ppTypeDescr)->ppAllMembers)
{
if (initTables) {
typelib_typedescription_initTables( *ppTypeDescr );
}
return true;
}
typelib_TypeDescription * pTD = 0;
// on demand access of complete td
TypeDescriptor_Init_Impl &rInit = Init::get();
rInit.callChain( &pTD, (*ppTypeDescr)->pTypeName );
if (pTD)
{
if (typelib_TypeClass_TYPEDEF == pTD->eTypeClass)
{
typelib_typedescriptionreference_getDescription(
&pTD, ((typelib_IndirectTypeDescription *)pTD)->pType );
OSL_ASSERT( pTD );
if (! pTD)
return false;
}
OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTD->eTypeClass );
// typedescription found
// set to on demand
pTD->bOnDemand = sal_True;
if (pTD->eTypeClass == typelib_TypeClass_INTERFACE
&& !pTD->bComplete && initTables)
{
// mandatory info from callback chain
OSL_ASSERT( ((typelib_InterfaceTypeDescription *)pTD)->ppAllMembers );
// complete except of tables init
typelib_typedescription_initTables( pTD );
pTD->bComplete = sal_True;
}
// The type description is hold by the reference until
// on demand is activated.
::typelib_typedescription_register( &pTD ); // replaces incomplete one
OSL_ASSERT( pTD == *ppTypeDescr ); // has to merge into existing one
// insert into the chache
MutexGuard aGuard( rInit.getMutex() );
if( !rInit.pCache )
rInit.pCache = new TypeDescriptionList_Impl;
if( (sal_Int32)rInit.pCache->size() >= nCacheSize )
{
typelib_typedescription_release( rInit.pCache->front() );
rInit.pCache->pop_front();
}
// descriptions in the cache must be acquired!
typelib_typedescription_acquire( pTD );
rInit.pCache->push_back( pTD );
OSL_ASSERT(
pTD->bComplete
|| (pTD->eTypeClass == typelib_TypeClass_INTERFACE
&& !initTables));
::typelib_typedescription_release( *ppTypeDescr );
*ppTypeDescr = pTD;
}
else
{
#if OSL_DEBUG_LEVEL > 1
OString aStr(
OUStringToOString( (*ppTypeDescr)->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
OSL_TRACE( "\n### type cannot be completed: %s", aStr.getStr() );
#endif
return false;
}
}
return true;
}
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newEmpty(
typelib_TypeDescription ** ppRet,
typelib_TypeClass eTypeClass, rtl_uString * pTypeName )
SAL_THROW_EXTERN_C()
{
if( *ppRet )
{
typelib_typedescription_release( *ppRet );
*ppRet = 0;
}
OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass );
typelib_TypeDescription * pRet;
switch( eTypeClass )
{
case typelib_TypeClass_ARRAY:
{
typelib_ArrayTypeDescription * pTmp = new typelib_ArrayTypeDescription();
typelib_IndirectTypeDescription * pIndirect = (typelib_IndirectTypeDescription *)pTmp;
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nArrayTypeDescriptionCount );
#endif
pIndirect->pType = 0;
pTmp->nDimensions = 0;
pTmp->nTotalElements = 0;
pTmp->pDimensions = 0;
}
break;
case typelib_TypeClass_SEQUENCE:
{
typelib_IndirectTypeDescription * pTmp = new typelib_IndirectTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nIndirectTypeDescriptionCount );
#endif
pTmp->pType = 0;
}
break;
case typelib_TypeClass_UNION:
{
typelib_UnionTypeDescription * pTmp;
pTmp = new typelib_UnionTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nUnionTypeDescriptionCount );
#endif
pTmp->nMembers = 0;
pTmp->pDiscriminantTypeRef = 0;
pTmp->pDiscriminants = 0;
pTmp->ppTypeRefs = 0;
pTmp->ppMemberNames = 0;
pTmp->pDefaultTypeRef = 0;
}
break;
case typelib_TypeClass_STRUCT:
{
// FEATURE_EMPTYCLASS
typelib_StructTypeDescription * pTmp;
pTmp = new typelib_StructTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nCompoundTypeDescriptionCount );
#endif
pTmp->aBase.pBaseTypeDescription = 0;
pTmp->aBase.nMembers = 0;
pTmp->aBase.pMemberOffsets = 0;
pTmp->aBase.ppTypeRefs = 0;
pTmp->aBase.ppMemberNames = 0;
pTmp->pParameterizedTypes = 0;
}
break;
case typelib_TypeClass_EXCEPTION:
{
// FEATURE_EMPTYCLASS
typelib_CompoundTypeDescription * pTmp;
pTmp = new typelib_CompoundTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nCompoundTypeDescriptionCount );
#endif
pTmp->pBaseTypeDescription = 0;
pTmp->nMembers = 0;
pTmp->pMemberOffsets = 0;
pTmp->ppTypeRefs = 0;
pTmp->ppMemberNames = 0;
}
break;
case typelib_TypeClass_ENUM:
{
typelib_EnumTypeDescription * pTmp = new typelib_EnumTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nEnumTypeDescriptionCount );
#endif
pTmp->nDefaultEnumValue = 0;
pTmp->nEnumValues = 0;
pTmp->ppEnumNames = 0;
pTmp->pEnumValues = 0;
}
break;
case typelib_TypeClass_INTERFACE:
{
typelib_InterfaceTypeDescription * pTmp = new typelib_InterfaceTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nInterfaceTypeDescriptionCount );
#endif
pTmp->pBaseTypeDescription = 0;
pTmp->nMembers = 0;
pTmp->ppMembers = 0;
pTmp->nAllMembers = 0;
pTmp->ppAllMembers = 0;
pTmp->nMapFunctionIndexToMemberIndex = 0;
pTmp->pMapFunctionIndexToMemberIndex = 0;
pTmp->pMapMemberIndexToFunctionIndex= 0;
pTmp->nBaseTypes = 0;
pTmp->ppBaseTypes = 0;
}
break;
case typelib_TypeClass_INTERFACE_METHOD:
{
typelib_InterfaceMethodTypeDescription * pTmp = new typelib_InterfaceMethodTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nInterfaceMethodTypeDescriptionCount );
#endif
pTmp->aBase.pMemberName = 0;
pTmp->pReturnTypeRef = 0;
pTmp->nParams = 0;
pTmp->pParams = 0;
pTmp->nExceptions = 0;
pTmp->ppExceptions = 0;
pTmp->pInterface = 0;
pTmp->pBaseRef = 0;
pTmp->nIndex = 0;
}
break;
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
typelib_InterfaceAttributeTypeDescription * pTmp = new typelib_InterfaceAttributeTypeDescription();
pRet = (typelib_TypeDescription *)pTmp;
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount(
&Init::get().nInterfaceAttributeTypeDescriptionCount );
#endif
pTmp->aBase.pMemberName = 0;
pTmp->pAttributeTypeRef = 0;
pTmp->pInterface = 0;
pTmp->pBaseRef = 0;
pTmp->nIndex = 0;
pTmp->nGetExceptions = 0;
pTmp->ppGetExceptions = 0;
pTmp->nSetExceptions = 0;
pTmp->ppSetExceptions = 0;
}
break;
default:
{
pRet = new typelib_TypeDescription();
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount( &Init::get().nTypeDescriptionCount );
#endif
}
}
pRet->nRefCount = 1; // reference count is initially 1
pRet->nStaticRefCount = 0;
pRet->eTypeClass = eTypeClass;
pRet->pTypeName = 0;
pRet->pUniqueIdentifier = 0;
pRet->pReserved = 0;
rtl_uString_acquire( pRet->pTypeName = pTypeName );
pRet->pSelf = pRet;
pRet->bComplete = sal_True;
pRet->nSize = 0;
pRet->nAlignment = 0;
pRet->pWeakRef = 0;
pRet->bOnDemand = sal_False;
*ppRet = pRet;
}
//------------------------------------------------------------------------
namespace {
void newTypeDescription(
typelib_TypeDescription ** ppRet, typelib_TypeClass eTypeClass,
rtl_uString * pTypeName, typelib_TypeDescriptionReference * pType,
sal_Int32 nMembers, typelib_CompoundMember_Init * pCompoundMembers,
typelib_StructMember_Init * pStructMembers)
{
OSL_ASSERT(
(pCompoundMembers == 0 || pStructMembers == 0)
&& (pStructMembers == 0 || eTypeClass == typelib_TypeClass_STRUCT));
if (typelib_TypeClass_TYPEDEF == eTypeClass)
{
OSL_TRACE( "### unexpected typedef!" );
typelib_typedescriptionreference_getDescription( ppRet, pType );
return;
}
typelib_typedescription_newEmpty( ppRet, eTypeClass, pTypeName );
switch( eTypeClass )
{
case typelib_TypeClass_SEQUENCE:
{
OSL_ASSERT( nMembers == 0 );
typelib_typedescriptionreference_acquire( pType );
((typelib_IndirectTypeDescription *)*ppRet)->pType = pType;
}
break;
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
{
// FEATURE_EMPTYCLASS
typelib_CompoundTypeDescription * pTmp = (typelib_CompoundTypeDescription*)*ppRet;
sal_Int32 nOffset = 0;
if( pType )
{
typelib_typedescriptionreference_getDescription(
(typelib_TypeDescription **)&pTmp->pBaseTypeDescription, pType );
nOffset = ((typelib_TypeDescription *)pTmp->pBaseTypeDescription)->nSize;
OSL_ENSURE( newAlignedSize( 0, ((typelib_TypeDescription *)pTmp->pBaseTypeDescription)->nSize, ((typelib_TypeDescription *)pTmp->pBaseTypeDescription)->nAlignment ) == ((typelib_TypeDescription *)pTmp->pBaseTypeDescription)->nSize, "### unexpected offset!" );
}
if( nMembers )
{
pTmp->nMembers = nMembers;
pTmp->pMemberOffsets = new sal_Int32[ nMembers ];
pTmp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ];
pTmp->ppMemberNames = new rtl_uString *[ nMembers ];
bool polymorphic = eTypeClass == typelib_TypeClass_STRUCT
&& rtl::OUString::unacquired(&pTypeName).indexOf('<') >= 0;
OSL_ASSERT(!polymorphic || pStructMembers != 0);
if (polymorphic) {
reinterpret_cast< typelib_StructTypeDescription * >(pTmp)->
pParameterizedTypes = new sal_Bool[nMembers];
}
for( sal_Int32 i = 0 ; i < nMembers; i++ )
{
// read the type and member names
pTmp->ppTypeRefs[i] = 0;
if (pCompoundMembers != 0) {
typelib_typedescriptionreference_new(
pTmp->ppTypeRefs +i, pCompoundMembers[i].eTypeClass,
pCompoundMembers[i].pTypeName );
rtl_uString_acquire(
pTmp->ppMemberNames[i]
= pCompoundMembers[i].pMemberName );
} else {
typelib_typedescriptionreference_new(
pTmp->ppTypeRefs +i,
pStructMembers[i].aBase.eTypeClass,
pStructMembers[i].aBase.pTypeName );
rtl_uString_acquire(
pTmp->ppMemberNames[i]
= pStructMembers[i].aBase.pMemberName );
}
// write offset
sal_Int32 size;
sal_Int32 alignment;
if (pTmp->ppTypeRefs[i]->eTypeClass ==
typelib_TypeClass_SEQUENCE)
{
// Take care of recursion like
// struct S { sequence<S> x; };
size = sizeof(void *);
alignment = adjustAlignment(size);
} else {
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, pTmp->ppTypeRefs[i] );
OSL_ENSURE( pTD->nSize, "### void member?" );
size = pTD->nSize;
alignment = pTD->nAlignment;
TYPELIB_DANGER_RELEASE( pTD );
}
nOffset = newAlignedSize( nOffset, size, alignment );
pTmp->pMemberOffsets[i] = nOffset - size;
if (polymorphic) {
reinterpret_cast< typelib_StructTypeDescription * >(
pTmp)->pParameterizedTypes[i]
= pStructMembers[i].bParameterizedType;
}
}
}
}
break;
default:
break;
}
if( !reallyWeak( eTypeClass ) )
(*ppRet)->pWeakRef = (typelib_TypeDescriptionReference *)*ppRet;
if( eTypeClass != typelib_TypeClass_VOID )
{
// sizeof( void ) not allowed
(*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( (*ppRet), 0, (*ppRet)->nAlignment );
(*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
}
}
}
extern "C" void SAL_CALL typelib_typedescription_new(
typelib_TypeDescription ** ppRet,
typelib_TypeClass eTypeClass,
rtl_uString * pTypeName,
typelib_TypeDescriptionReference * pType,
sal_Int32 nMembers,
typelib_CompoundMember_Init * pMembers )
SAL_THROW_EXTERN_C()
{
newTypeDescription(
ppRet, eTypeClass, pTypeName, pType, nMembers, pMembers, 0);
}
extern "C" void SAL_CALL typelib_typedescription_newStruct(
typelib_TypeDescription ** ppRet,
rtl_uString * pTypeName,
typelib_TypeDescriptionReference * pType,
sal_Int32 nMembers,
typelib_StructMember_Init * pMembers )
SAL_THROW_EXTERN_C()
{
newTypeDescription(
ppRet, typelib_TypeClass_STRUCT, pTypeName, pType, nMembers, 0,
pMembers);
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newUnion(
typelib_TypeDescription ** ppRet,
rtl_uString * pTypeName,
typelib_TypeDescriptionReference * pDiscriminantTypeRef,
sal_Int64 nDefaultDiscriminant,
typelib_TypeDescriptionReference * pDefaultTypeRef,
sal_Int32 nMembers,
typelib_Union_Init * pMembers )
SAL_THROW_EXTERN_C()
{
typelib_typedescription_newEmpty( ppRet, typelib_TypeClass_UNION, pTypeName );
// discriminant type
typelib_UnionTypeDescription * pTmp = (typelib_UnionTypeDescription *)*ppRet;
typelib_typedescriptionreference_acquire( pTmp->pDiscriminantTypeRef = pDiscriminantTypeRef );
sal_Int32 nPos;
pTmp->nMembers = nMembers;
// default discriminant
if (nMembers)
{
pTmp->pDiscriminants = new sal_Int64[ nMembers ];
for ( nPos = nMembers; nPos--; )
{
pTmp->pDiscriminants[nPos] = pMembers[nPos].nDiscriminant;
}
}
// default default discriminant
pTmp->nDefaultDiscriminant = nDefaultDiscriminant;
// union member types
pTmp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ];
for ( nPos = nMembers; nPos--; )
{
typelib_typedescriptionreference_acquire( pTmp->ppTypeRefs[nPos] = pMembers[nPos].pTypeRef );
}
// union member names
pTmp->ppMemberNames = new rtl_uString *[ nMembers ];
for ( nPos = nMembers; nPos--; )
{
rtl_uString_acquire( pTmp->ppMemberNames[nPos] = pMembers[nPos].pMemberName );
}
// default union type
typelib_typedescriptionreference_acquire( pTmp->pDefaultTypeRef = pDefaultTypeRef );
if (! reallyWeak( typelib_TypeClass_UNION ))
(*ppRet)->pWeakRef = (typelib_TypeDescriptionReference *)*ppRet;
(*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( (*ppRet), 0, (*ppRet)->nAlignment );
(*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newEnum(
typelib_TypeDescription ** ppRet,
rtl_uString * pTypeName,
sal_Int32 nDefaultValue,
sal_Int32 nEnumValues,
rtl_uString ** ppEnumNames,
sal_Int32 * pEnumValues )
SAL_THROW_EXTERN_C()
{
typelib_typedescription_newEmpty( ppRet, typelib_TypeClass_ENUM, pTypeName );
typelib_EnumTypeDescription * pEnum = (typelib_EnumTypeDescription *)*ppRet;
pEnum->nDefaultEnumValue = nDefaultValue;
pEnum->nEnumValues = nEnumValues;
pEnum->ppEnumNames = new rtl_uString * [ nEnumValues ];
for ( sal_Int32 nPos = nEnumValues; nPos--; )
{
rtl_uString_acquire( pEnum->ppEnumNames[nPos] = ppEnumNames[nPos] );
}
pEnum->pEnumValues = new sal_Int32[ nEnumValues ];
::memcpy( pEnum->pEnumValues, pEnumValues, nEnumValues * sizeof(sal_Int32) );
(*ppRet)->pWeakRef = (typelib_TypeDescriptionReference *)*ppRet;
// sizeof( void ) not allowed
(*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( (*ppRet), 0, (*ppRet)->nAlignment );
(*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newArray(
typelib_TypeDescription ** ppRet,
typelib_TypeDescriptionReference * pElementTypeRef,
sal_Int32 nDimensions,
sal_Int32 * pDimensions )
SAL_THROW_EXTERN_C ()
{
OUStringBuffer aBuf( 32 );
aBuf.append( pElementTypeRef->pTypeName );
sal_Int32 nElements = 1;
for (sal_Int32 i=0; i < nDimensions; i++)
{
aBuf.appendAscii("[");
aBuf.append(pDimensions[i]);
aBuf.appendAscii("]");
nElements *= pDimensions[i];
}
OUString aTypeName( aBuf.makeStringAndClear() );
typelib_typedescription_newEmpty( ppRet, typelib_TypeClass_ARRAY, aTypeName.pData );
typelib_ArrayTypeDescription * pArray = (typelib_ArrayTypeDescription *)*ppRet;
pArray->nDimensions = nDimensions;
pArray->nTotalElements = nElements;
pArray->pDimensions = new sal_Int32[ nDimensions ];
::memcpy( pArray->pDimensions, pDimensions, nDimensions * sizeof(sal_Int32) );
typelib_typedescriptionreference_acquire(pElementTypeRef);
((typelib_IndirectTypeDescription*)pArray)->pType = pElementTypeRef;
(*ppRet)->pWeakRef = (typelib_TypeDescriptionReference *)*ppRet;
// sizeof( void ) not allowed
(*ppRet)->nSize = typelib_typedescription_getAlignedUnoSize( *ppRet, 0, (*ppRet)->nAlignment );
(*ppRet)->nAlignment = adjustAlignment( (*ppRet)->nAlignment );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newInterface(
typelib_InterfaceTypeDescription ** ppRet,
rtl_uString * pTypeName,
sal_uInt32 nUik1, sal_uInt16 nUik2, sal_uInt16 nUik3, sal_uInt32 nUik4, sal_uInt32 nUik5,
typelib_TypeDescriptionReference * pBaseInterface,
sal_Int32 nMembers,
typelib_TypeDescriptionReference ** ppMembers )
SAL_THROW_EXTERN_C()
{
typelib_typedescription_newMIInterface(
ppRet, pTypeName, nUik1, nUik2, nUik3, nUik4, nUik5,
pBaseInterface == 0 ? 0 : 1, &pBaseInterface, nMembers, ppMembers);
}
//------------------------------------------------------------------------
namespace {
class BaseList {
public:
struct Entry {
sal_Int32 memberOffset;
sal_Int32 directBaseIndex;
sal_Int32 directBaseMemberOffset;
typelib_InterfaceTypeDescription const * base;
};
typedef std::vector< Entry > List;
BaseList(typelib_InterfaceTypeDescription const * desc);
List const & getList() const { return list; }
sal_Int32 getBaseMembers() const { return members; }
private:
typedef std::set< rtl::OUString > Set;
void calculate(
sal_Int32 directBaseIndex, Set & directBaseSet,
sal_Int32 * directBaseMembers,
typelib_InterfaceTypeDescription const * desc);
Set set;
List list;
sal_Int32 members;
};
BaseList::BaseList(typelib_InterfaceTypeDescription const * desc) {
members = 0;
for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) {
Set directBaseSet;
sal_Int32 directBaseMembers = 0;
calculate(i, directBaseSet, &directBaseMembers, desc->ppBaseTypes[i]);
}
}
void BaseList::calculate(
sal_Int32 directBaseIndex, Set & directBaseSet,
sal_Int32 * directBaseMembers,
typelib_InterfaceTypeDescription const * desc)
{
for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) {
calculate(
directBaseIndex, directBaseSet, directBaseMembers,
desc->ppBaseTypes[i]);
}
if (set.insert(desc->aBase.pTypeName).second) {
Entry e;
e.memberOffset = members;
e.directBaseIndex = directBaseIndex;
e.directBaseMemberOffset = *directBaseMembers;
e.base = desc;
list.push_back(e);
OSL_ASSERT(desc->ppAllMembers != 0);
members += desc->nMembers;
}
if (directBaseSet.insert(desc->aBase.pTypeName).second) {
OSL_ASSERT(desc->ppAllMembers != 0);
*directBaseMembers += desc->nMembers;
}
}
}
extern "C" void SAL_CALL typelib_typedescription_newMIInterface(
typelib_InterfaceTypeDescription ** ppRet,
rtl_uString * pTypeName,
sal_uInt32 nUik1, sal_uInt16 nUik2, sal_uInt16 nUik3, sal_uInt32 nUik4, sal_uInt32 nUik5,
sal_Int32 nBaseInterfaces,
typelib_TypeDescriptionReference ** ppBaseInterfaces,
sal_Int32 nMembers,
typelib_TypeDescriptionReference ** ppMembers )
SAL_THROW_EXTERN_C()
{
if (*ppRet != 0) {
typelib_typedescription_release(&(*ppRet)->aBase);
*ppRet = 0;
}
typelib_InterfaceTypeDescription * pITD = 0;
typelib_typedescription_newEmpty(
(typelib_TypeDescription **)&pITD, typelib_TypeClass_INTERFACE, pTypeName );
pITD->nBaseTypes = nBaseInterfaces;
pITD->ppBaseTypes = new typelib_InterfaceTypeDescription *[nBaseInterfaces];
for (sal_Int32 i = 0; i < nBaseInterfaces; ++i) {
pITD->ppBaseTypes[i] = 0;
typelib_typedescriptionreference_getDescription(
reinterpret_cast< typelib_TypeDescription ** >(
&pITD->ppBaseTypes[i]),
ppBaseInterfaces[i]);
if (pITD->ppBaseTypes[i] == 0
|| !complete(
reinterpret_cast< typelib_TypeDescription ** >(
&pITD->ppBaseTypes[i]),
false))
{
OSL_ASSERT(false);
return;
}
OSL_ASSERT(pITD->ppBaseTypes[i] != 0);
}
if (nBaseInterfaces > 0) {
pITD->pBaseTypeDescription = pITD->ppBaseTypes[0];
}
// set the
pITD->aUik.m_Data1 = nUik1;
pITD->aUik.m_Data2 = nUik2;
pITD->aUik.m_Data3 = nUik3;
pITD->aUik.m_Data4 = nUik4;
pITD->aUik.m_Data5 = nUik5;
BaseList aBaseList(pITD);
pITD->nAllMembers = nMembers + aBaseList.getBaseMembers();
pITD->nMembers = nMembers;
if( pITD->nAllMembers )
{
// at minimum one member exist, allocate the memory
pITD->ppAllMembers = new typelib_TypeDescriptionReference *[ pITD->nAllMembers ];
sal_Int32 n = 0;
BaseList::List const & rList = aBaseList.getList();
{for (BaseList::List::const_iterator i(rList.begin()); i != rList.end();
++i)
{
typelib_InterfaceTypeDescription const * pBase = i->base;
typelib_InterfaceTypeDescription const * pDirectBase
= pITD->ppBaseTypes[i->directBaseIndex];
OSL_ASSERT(pBase->ppAllMembers != 0);
for (sal_Int32 j = 0; j < pBase->nMembers; ++j) {
typelib_TypeDescriptionReference const * pDirectBaseMember
= pDirectBase->ppAllMembers[i->directBaseMemberOffset + j];
rtl::OUStringBuffer aBuf(pDirectBaseMember->pTypeName);
aBuf.appendAscii(RTL_CONSTASCII_STRINGPARAM(":@"));
aBuf.append(i->directBaseIndex);
aBuf.append(static_cast< sal_Unicode >(','));
aBuf.append(i->memberOffset + j);
aBuf.append(static_cast< sal_Unicode >(':'));
aBuf.append(pITD->aBase.pTypeName);
rtl::OUString aName(aBuf.makeStringAndClear());
typelib_TypeDescriptionReference * pDerivedMember = 0;
typelib_typedescriptionreference_new(
&pDerivedMember, pDirectBaseMember->eTypeClass,
aName.pData);
pITD->ppAllMembers[n++] = pDerivedMember;
}
}}
if( nMembers )
{
pITD->ppMembers = pITD->ppAllMembers + aBaseList.getBaseMembers();
}
// add own members
{for( sal_Int32 i = 0; i < nMembers; i++ )
{
typelib_typedescriptionreference_acquire( ppMembers[i] );
pITD->ppAllMembers[n++] = ppMembers[i];
}}
}
typelib_TypeDescription * pTmp = (typelib_TypeDescription *)pITD;
if( !reallyWeak( typelib_TypeClass_INTERFACE ) )
pTmp->pWeakRef = (typelib_TypeDescriptionReference *)pTmp;
pTmp->nSize = typelib_typedescription_getAlignedUnoSize( pTmp, 0, pTmp->nAlignment );
pTmp->nAlignment = adjustAlignment( pTmp->nAlignment );
pTmp->bComplete = sal_False;
*ppRet = pITD;
}
//------------------------------------------------------------------------
namespace {
typelib_TypeDescriptionReference ** copyExceptions(
sal_Int32 count, rtl_uString ** typeNames)
{
OSL_ASSERT(count >= 0);
if (count == 0) {
return 0;
}
typelib_TypeDescriptionReference ** p
= new typelib_TypeDescriptionReference *[count];
for (sal_Int32 i = 0; i < count; ++i) {
p[i] = 0;
typelib_typedescriptionreference_new(
p + i, typelib_TypeClass_EXCEPTION, typeNames[i]);
}
return p;
}
}
extern "C" void SAL_CALL typelib_typedescription_newInterfaceMethod(
typelib_InterfaceMethodTypeDescription ** ppRet,
sal_Int32 nAbsolutePosition,
sal_Bool bOneWay,
rtl_uString * pTypeName,
typelib_TypeClass eReturnTypeClass,
rtl_uString * pReturnTypeName,
sal_Int32 nParams,
typelib_Parameter_Init * pParams,
sal_Int32 nExceptions,
rtl_uString ** ppExceptionNames )
SAL_THROW_EXTERN_C()
{
if (*ppRet != 0) {
typelib_typedescription_release(&(*ppRet)->aBase.aBase);
*ppRet = 0;
}
sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength(
pTypeName->buffer, pTypeName->length, ':');
if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') {
OSL_ENSURE(false, "Bad interface method type name");
return;
}
rtl::OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1);
typelib_InterfaceTypeDescription * pInterface = 0;
typelib_typedescription_getByName(
reinterpret_cast< typelib_TypeDescription ** >(&pInterface),
aInterfaceTypeName.pData);
if (pInterface == 0
|| pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE
|| !complete(
reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false))
{
OSL_ENSURE(false, "No interface corresponding to interface method");
return;
}
typelib_typedescription_newEmpty(
(typelib_TypeDescription **)ppRet, typelib_TypeClass_INTERFACE_METHOD, pTypeName );
typelib_TypeDescription * pTmp = (typelib_TypeDescription *)*ppRet;
rtl_uString_newFromStr_WithLength( &(*ppRet)->aBase.pMemberName,
pTypeName->buffer + nOffset +1,
pTypeName->length - nOffset -1 );
(*ppRet)->aBase.nPosition = nAbsolutePosition;
(*ppRet)->bOneWay = bOneWay;
typelib_typedescriptionreference_new( &(*ppRet)->pReturnTypeRef, eReturnTypeClass, pReturnTypeName );
(*ppRet)->nParams = nParams;
if( nParams )
{
(*ppRet)->pParams = new typelib_MethodParameter[ nParams ];
for( sal_Int32 i = 0; i < nParams; i++ )
{
// get the name of the parameter
(*ppRet)->pParams[ i ].pName = 0;
rtl_uString_acquire( (*ppRet)->pParams[ i ].pName = pParams[i].pParamName );
(*ppRet)->pParams[ i ].pTypeRef = 0;
// get the type name of the parameter and create the weak reference
typelib_typedescriptionreference_new(
&(*ppRet)->pParams[ i ].pTypeRef, pParams[i].eTypeClass, pParams[i].pTypeName );
(*ppRet)->pParams[ i ].bIn = pParams[i].bIn;
(*ppRet)->pParams[ i ].bOut = pParams[i].bOut;
}
}
(*ppRet)->nExceptions = nExceptions;
(*ppRet)->ppExceptions = copyExceptions(nExceptions, ppExceptionNames);
(*ppRet)->pInterface = pInterface;
(*ppRet)->pBaseRef = 0;
OSL_ASSERT(
(nAbsolutePosition >= pInterface->nAllMembers - pInterface->nMembers)
&& nAbsolutePosition < pInterface->nAllMembers);
(*ppRet)->nIndex = nAbsolutePosition
- (pInterface->nAllMembers - pInterface->nMembers);
if( !reallyWeak( typelib_TypeClass_INTERFACE_METHOD ) )
pTmp->pWeakRef = (typelib_TypeDescriptionReference *)pTmp;
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newInterfaceAttribute(
typelib_InterfaceAttributeTypeDescription ** ppRet,
sal_Int32 nAbsolutePosition,
rtl_uString * pTypeName,
typelib_TypeClass eAttributeTypeClass,
rtl_uString * pAttributeTypeName,
sal_Bool bReadOnly )
SAL_THROW_EXTERN_C()
{
typelib_typedescription_newExtendedInterfaceAttribute(
ppRet, nAbsolutePosition, pTypeName, eAttributeTypeClass,
pAttributeTypeName, bReadOnly, 0, 0, 0, 0);
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_newExtendedInterfaceAttribute(
typelib_InterfaceAttributeTypeDescription ** ppRet,
sal_Int32 nAbsolutePosition,
rtl_uString * pTypeName,
typelib_TypeClass eAttributeTypeClass,
rtl_uString * pAttributeTypeName,
sal_Bool bReadOnly,
sal_Int32 nGetExceptions, rtl_uString ** ppGetExceptionNames,
sal_Int32 nSetExceptions, rtl_uString ** ppSetExceptionNames )
SAL_THROW_EXTERN_C()
{
if (*ppRet != 0) {
typelib_typedescription_release(&(*ppRet)->aBase.aBase);
*ppRet = 0;
}
sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength(
pTypeName->buffer, pTypeName->length, ':');
if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') {
OSL_ENSURE(false, "Bad interface attribute type name");
return;
}
rtl::OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1);
typelib_InterfaceTypeDescription * pInterface = 0;
typelib_typedescription_getByName(
reinterpret_cast< typelib_TypeDescription ** >(&pInterface),
aInterfaceTypeName.pData);
if (pInterface == 0
|| pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE
|| !complete(
reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false))
{
OSL_ENSURE(false, "No interface corresponding to interface attribute");
return;
}
typelib_typedescription_newEmpty(
(typelib_TypeDescription **)ppRet, typelib_TypeClass_INTERFACE_ATTRIBUTE, pTypeName );
typelib_TypeDescription * pTmp = (typelib_TypeDescription *)*ppRet;
rtl_uString_newFromStr_WithLength( &(*ppRet)->aBase.pMemberName,
pTypeName->buffer + nOffset +1,
pTypeName->length - nOffset -1 );
(*ppRet)->aBase.nPosition = nAbsolutePosition;
typelib_typedescriptionreference_new( &(*ppRet)->pAttributeTypeRef, eAttributeTypeClass, pAttributeTypeName );
(*ppRet)->bReadOnly = bReadOnly;
(*ppRet)->pInterface = pInterface;
(*ppRet)->pBaseRef = 0;
OSL_ASSERT(
(nAbsolutePosition >= pInterface->nAllMembers - pInterface->nMembers)
&& nAbsolutePosition < pInterface->nAllMembers);
(*ppRet)->nIndex = nAbsolutePosition
- (pInterface->nAllMembers - pInterface->nMembers);
(*ppRet)->nGetExceptions = nGetExceptions;
(*ppRet)->ppGetExceptions = copyExceptions(
nGetExceptions, ppGetExceptionNames);
(*ppRet)->nSetExceptions = nSetExceptions;
(*ppRet)->ppSetExceptions = copyExceptions(
nSetExceptions, ppSetExceptionNames);
if( !reallyWeak( typelib_TypeClass_INTERFACE_ATTRIBUTE ) )
pTmp->pWeakRef = (typelib_TypeDescriptionReference *)pTmp;
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_acquire(
typelib_TypeDescription * pTypeDescription )
SAL_THROW_EXTERN_C()
{
::osl_incrementInterlockedCount( &pTypeDescription->nRefCount );
}
//------------------------------------------------------------------------
namespace {
void deleteExceptions(
sal_Int32 count, typelib_TypeDescriptionReference ** exceptions)
{
for (sal_Int32 i = 0; i < count; ++i) {
typelib_typedescriptionreference_release(exceptions[i]);
}
delete[] exceptions;
}
}
// frees anything except typelib_TypeDescription base!
static inline void typelib_typedescription_destructExtendedMembers(
typelib_TypeDescription * pTD )
SAL_THROW( () )
{
OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTD->eTypeClass );
switch( pTD->eTypeClass )
{
case typelib_TypeClass_ARRAY:
if( ((typelib_IndirectTypeDescription*)pTD)->pType )
typelib_typedescriptionreference_release( ((typelib_IndirectTypeDescription*)pTD)->pType );
delete [] ((typelib_ArrayTypeDescription *)pTD)->pDimensions;
break;
case typelib_TypeClass_SEQUENCE:
if( ((typelib_IndirectTypeDescription*)pTD)->pType )
typelib_typedescriptionreference_release( ((typelib_IndirectTypeDescription*)pTD)->pType );
break;
case typelib_TypeClass_UNION:
{
typelib_UnionTypeDescription * pUnionTD = (typelib_UnionTypeDescription *)pTD;
typelib_typedescriptionreference_release( pUnionTD->pDiscriminantTypeRef );
typelib_typedescriptionreference_release( pUnionTD->pDefaultTypeRef );
sal_Int32 nPos;
typelib_TypeDescriptionReference ** ppTypeRefs = pUnionTD->ppTypeRefs;
for ( nPos = pUnionTD->nMembers; nPos--; )
{
typelib_typedescriptionreference_release( ppTypeRefs[nPos] );
}
rtl_uString ** ppMemberNames = pUnionTD->ppMemberNames;
for ( nPos = pUnionTD->nMembers; nPos--; )
{
rtl_uString_release( ppMemberNames[nPos] );
}
delete [] pUnionTD->ppMemberNames;
delete [] pUnionTD->pDiscriminants;
delete [] pUnionTD->ppTypeRefs;
}
break;
case typelib_TypeClass_STRUCT:
delete[] reinterpret_cast< typelib_StructTypeDescription * >(pTD)->
pParameterizedTypes;
case typelib_TypeClass_EXCEPTION:
{
typelib_CompoundTypeDescription * pCTD = (typelib_CompoundTypeDescription*)pTD;
if( pCTD->pBaseTypeDescription )
typelib_typedescription_release( (typelib_TypeDescription *)pCTD->pBaseTypeDescription );
sal_Int32 i;
for( i = 0; i < pCTD->nMembers; i++ )
{
typelib_typedescriptionreference_release( pCTD->ppTypeRefs[i] );
}
if (pCTD->ppMemberNames)
{
for ( i = 0; i < pCTD->nMembers; i++ )
{
rtl_uString_release( pCTD->ppMemberNames[i] );
}
delete [] pCTD->ppMemberNames;
}
delete [] pCTD->ppTypeRefs;
delete [] pCTD->pMemberOffsets;
}
break;
case typelib_TypeClass_INTERFACE:
{
typelib_InterfaceTypeDescription * pITD = (typelib_InterfaceTypeDescription*)pTD;
{for( sal_Int32 i = 0; i < pITD->nAllMembers; i++ )
{
typelib_typedescriptionreference_release( pITD->ppAllMembers[i] );
}}
delete [] pITD->ppAllMembers;
delete [] pITD->pMapMemberIndexToFunctionIndex;
delete [] pITD->pMapFunctionIndexToMemberIndex;
{for (sal_Int32 i = 0; i < pITD->nBaseTypes; ++i) {
typelib_typedescription_release(
reinterpret_cast< typelib_TypeDescription * >(
pITD->ppBaseTypes[i]));
}}
delete[] pITD->ppBaseTypes;
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
typelib_InterfaceMethodTypeDescription * pIMTD = (typelib_InterfaceMethodTypeDescription*)pTD;
if( pIMTD->pReturnTypeRef )
typelib_typedescriptionreference_release( pIMTD->pReturnTypeRef );
for( sal_Int32 i = 0; i < pIMTD->nParams; i++ )
{
rtl_uString_release( pIMTD->pParams[ i ].pName );
typelib_typedescriptionreference_release( pIMTD->pParams[ i ].pTypeRef );
}
delete [] pIMTD->pParams;
deleteExceptions(pIMTD->nExceptions, pIMTD->ppExceptions);
rtl_uString_release( pIMTD->aBase.pMemberName );
typelib_typedescription_release(&pIMTD->pInterface->aBase);
if (pIMTD->pBaseRef != 0) {
typelib_typedescriptionreference_release(pIMTD->pBaseRef);
}
}
break;
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
typelib_InterfaceAttributeTypeDescription * pIATD = (typelib_InterfaceAttributeTypeDescription*)pTD;
deleteExceptions(pIATD->nGetExceptions, pIATD->ppGetExceptions);
deleteExceptions(pIATD->nSetExceptions, pIATD->ppSetExceptions);
if( pIATD->pAttributeTypeRef )
typelib_typedescriptionreference_release( pIATD->pAttributeTypeRef );
if( pIATD->aBase.pMemberName )
rtl_uString_release( pIATD->aBase.pMemberName );
typelib_typedescription_release(&pIATD->pInterface->aBase);
if (pIATD->pBaseRef != 0) {
typelib_typedescriptionreference_release(pIATD->pBaseRef);
}
}
break;
case typelib_TypeClass_ENUM:
{
typelib_EnumTypeDescription * pEnum = (typelib_EnumTypeDescription *)pTD;
for ( sal_Int32 nPos = pEnum->nEnumValues; nPos--; )
{
rtl_uString_release( pEnum->ppEnumNames[nPos] );
}
delete [] pEnum->ppEnumNames;
delete [] pEnum->pEnumValues;
}
break;
default:
break;
}
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_release(
typelib_TypeDescription * pTD )
SAL_THROW_EXTERN_C()
{
sal_Int32 ref = ::osl_decrementInterlockedCount( &pTD->nRefCount );
OSL_ASSERT(ref >= 0);
if (0 == ref)
{
TypeDescriptor_Init_Impl &rInit = Init::get();
if( reallyWeak( pTD->eTypeClass ) )
{
if( pTD->pWeakRef )
{
{
MutexGuard aGuard( rInit.getMutex() );
// remove this description from the weak reference
pTD->pWeakRef->pType = 0;
}
typelib_typedescriptionreference_release( pTD->pWeakRef );
}
}
else
{
// this description is a reference too, so remove it from the hash table
if( rInit.pWeakMap )
{
MutexGuard aGuard( rInit.getMutex() );
WeakMap_Impl::iterator aIt = rInit.pWeakMap->find( (sal_Unicode*)pTD->pTypeName->buffer );
if( aIt != rInit.pWeakMap->end() && (void *)(*aIt).second == (void *)pTD )
{
// remove only if it contains the same object
rInit.pWeakMap->erase( aIt );
}
}
}
typelib_typedescription_destructExtendedMembers( pTD );
rtl_uString_release( pTD->pTypeName );
#if OSL_DEBUG_LEVEL > 1
switch( pTD->eTypeClass )
{
case typelib_TypeClass_ARRAY:
osl_decrementInterlockedCount( &rInit.nArrayTypeDescriptionCount );
break;
case typelib_TypeClass_SEQUENCE:
osl_decrementInterlockedCount( &rInit.nIndirectTypeDescriptionCount );
break;
case typelib_TypeClass_UNION:
osl_decrementInterlockedCount( &rInit.nUnionTypeDescriptionCount );
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
osl_decrementInterlockedCount( &rInit.nCompoundTypeDescriptionCount );
break;
case typelib_TypeClass_INTERFACE:
osl_decrementInterlockedCount( &rInit.nInterfaceTypeDescriptionCount );
break;
case typelib_TypeClass_INTERFACE_METHOD:
osl_decrementInterlockedCount( &rInit.nInterfaceMethodTypeDescriptionCount );
break;
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
osl_decrementInterlockedCount( &rInit.nInterfaceAttributeTypeDescriptionCount );
break;
case typelib_TypeClass_ENUM:
osl_decrementInterlockedCount( &rInit.nEnumTypeDescriptionCount );
break;
default:
osl_decrementInterlockedCount( &rInit.nTypeDescriptionCount );
}
#endif
delete pTD;
}
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescription_register(
typelib_TypeDescription ** ppNewDescription )
SAL_THROW_EXTERN_C()
{
// connect the description with the weak reference
TypeDescriptor_Init_Impl &rInit = Init::get();
ClearableMutexGuard aGuard( rInit.getMutex() );
typelib_TypeDescriptionReference * pTDR = 0;
typelib_typedescriptionreference_getByName( &pTDR, (*ppNewDescription)->pTypeName );
OSL_ASSERT( (*ppNewDescription)->pWeakRef || reallyWeak( (*ppNewDescription)->eTypeClass ) );
if( pTDR )
{
OSL_ASSERT( (*ppNewDescription)->eTypeClass == pTDR->eTypeClass );
if( pTDR->pType )
{
if (reallyWeak( pTDR->eTypeClass ))
{
// pRef->pType->pWeakRef == 0 means that the description is empty
if (pTDR->pType->pWeakRef)
{
if (osl_incrementInterlockedCount( &pTDR->pType->nRefCount ) > 1)
{
// The refence is incremented. The object cannot be destroyed.
// Release the guard at the earliest point.
aGuard.clear();
::typelib_typedescription_release( *ppNewDescription );
*ppNewDescription = pTDR->pType;
::typelib_typedescriptionreference_release( pTDR );
return;
}
else
{
// destruction of this type in progress (another thread!)
osl_decrementInterlockedCount( &pTDR->pType->nRefCount );
}
}
// take new descr
pTDR->pType = *ppNewDescription;
OSL_ASSERT( ! (*ppNewDescription)->pWeakRef );
(*ppNewDescription)->pWeakRef = pTDR;
return;
}
// !reallyWeak
if (((void *)pTDR != (void *)*ppNewDescription) && // if different
(!pTDR->pType->pWeakRef || // uninit: ref data only set
// new one is complete:
(!pTDR->pType->bComplete && (*ppNewDescription)->bComplete) ||
// new one may be partly initialized interface (except of tables):
(typelib_TypeClass_INTERFACE == pTDR->pType->eTypeClass &&
!((typelib_InterfaceTypeDescription *)pTDR->pType)->ppAllMembers &&
(*(typelib_InterfaceTypeDescription **)ppNewDescription)->ppAllMembers)))
{
// uninitialized or incomplete
if (pTDR->pType->pWeakRef) // if init
{
typelib_typedescription_destructExtendedMembers( pTDR->pType );
}
// pTDR->pType->pWeakRef == 0 means that the description is empty
// description is not weak and the not the same
sal_Int32 nSize = getDescriptionSize( (*ppNewDescription)->eTypeClass );
// copy all specific data for the descriptions
::rtl_copyMemory(
pTDR->pType +1,
*ppNewDescription +1,
nSize - sizeof(typelib_TypeDescription) );
pTDR->pType->bComplete = (*ppNewDescription)->bComplete;
pTDR->pType->nSize = (*ppNewDescription)->nSize;
pTDR->pType->nAlignment = (*ppNewDescription)->nAlignment;
::rtl_zeroMemory(
*ppNewDescription +1, nSize - sizeof( typelib_TypeDescription ) );
if( pTDR->pType->bOnDemand && !(*ppNewDescription)->bOnDemand )
{
// switch from OnDemand to !OnDemand, so the description must be acquired
typelib_typedescription_acquire( pTDR->pType );
}
else if( !pTDR->pType->bOnDemand && (*ppNewDescription)->bOnDemand )
{
// switch from !OnDemand to OnDemand, so the description must be relesed
typelib_typedescription_release( pTDR->pType );
}
pTDR->pType->bOnDemand = (*ppNewDescription)->bOnDemand;
// initialized
pTDR->pType->pWeakRef = pTDR;
}
typelib_typedescription_release( *ppNewDescription );
// pTDR was acquired by getByName(), so it must not be acquired again
*ppNewDescription = pTDR->pType;
return;
}
}
else if( reallyWeak( (*ppNewDescription)->eTypeClass) )
{
typelib_typedescriptionreference_new(
&pTDR, (*ppNewDescription)->eTypeClass, (*ppNewDescription)->pTypeName );
}
else
{
pTDR = (typelib_TypeDescriptionReference *)*ppNewDescription;
if( !rInit.pWeakMap )
rInit.pWeakMap = new WeakMap_Impl;
// description is the weak itself, so register it
(*rInit.pWeakMap)[pTDR->pTypeName->buffer] = pTDR;
OSL_ASSERT( (void *)*ppNewDescription == (void *)pTDR );
}
// By default this reference is not really weak. The reference hold the description
// and the description hold the reference.
if( !(*ppNewDescription)->bOnDemand )
{
// nor OnDemand so the description must be acquired if registered
typelib_typedescription_acquire( *ppNewDescription );
}
pTDR->pType = *ppNewDescription;
(*ppNewDescription)->pWeakRef = pTDR;
OSL_ASSERT( rtl_ustr_compare( pTDR->pTypeName->buffer, (*ppNewDescription)->pTypeName->buffer ) == 0 );
OSL_ASSERT( pTDR->eTypeClass == (*ppNewDescription)->eTypeClass );
}
//------------------------------------------------------------------------
static inline sal_Bool type_equals(
typelib_TypeDescriptionReference * p1, typelib_TypeDescriptionReference * p2 )
SAL_THROW( () )
{
return (p1 == p2 ||
(p1->eTypeClass == p2->eTypeClass &&
p1->pTypeName->length == p2->pTypeName->length &&
rtl_ustr_compare( p1->pTypeName->buffer, p2->pTypeName->buffer ) == 0));
}
extern "C" sal_Bool SAL_CALL typelib_typedescription_equals(
const typelib_TypeDescription * p1, const typelib_TypeDescription * p2 )
SAL_THROW_EXTERN_C()
{
return type_equals(
(typelib_TypeDescriptionReference *)p1, (typelib_TypeDescriptionReference *)p2 );
}
//------------------------------------------------------------------------
extern "C" sal_Int32 SAL_CALL typelib_typedescription_getAlignedUnoSize(
const typelib_TypeDescription * pTypeDescription,
sal_Int32 nOffset, sal_Int32 & rMaxIntegralTypeSize )
SAL_THROW_EXTERN_C()
{
sal_Int32 nSize;
if( pTypeDescription->nSize )
{
// size and alignment are set
rMaxIntegralTypeSize = pTypeDescription->nAlignment;
nSize = pTypeDescription->nSize;
}
else
{
nSize = 0;
rMaxIntegralTypeSize = 1;
OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTypeDescription->eTypeClass );
switch( pTypeDescription->eTypeClass )
{
case typelib_TypeClass_INTERFACE:
// FEATURE_INTERFACE
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( void * ));
break;
case typelib_TypeClass_UNION:
{
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof(sal_Int64));
for ( sal_Int32 nPos = ((typelib_UnionTypeDescription *)pTypeDescription)->nMembers; nPos--; )
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, ((typelib_UnionTypeDescription *)pTypeDescription)->ppTypeRefs[nPos] );
sal_Int32 nMaxIntegralTypeSize;
sal_Int32 nMemberSize = typelib_typedescription_getAlignedUnoSize( pTD, (sal_Int32)(sizeof(sal_Int64)), nMaxIntegralTypeSize );
TYPELIB_DANGER_RELEASE( pTD );
if (nSize < nMemberSize)
nSize = nMemberSize;
if (rMaxIntegralTypeSize < nMaxIntegralTypeSize)
rMaxIntegralTypeSize = nMaxIntegralTypeSize;
}
((typelib_UnionTypeDescription *)pTypeDescription)->nValueOffset = rMaxIntegralTypeSize;
}
break;
case typelib_TypeClass_ENUM:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( typelib_TypeClass ));
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
// FEATURE_EMPTYCLASS
{
typelib_CompoundTypeDescription * pTmp = (typelib_CompoundTypeDescription *)pTypeDescription;
sal_Int32 nStructSize = 0;
if( pTmp->pBaseTypeDescription )
{
// inherit structs extends the base struct.
nStructSize = pTmp->pBaseTypeDescription->aBase.nSize;
rMaxIntegralTypeSize = pTmp->pBaseTypeDescription->aBase.nAlignment;
}
for( sal_Int32 i = 0; i < pTmp->nMembers; i++ )
{
typelib_TypeDescription * pMemberType = 0;
typelib_TypeDescriptionReference * pMemberRef = pTmp->ppTypeRefs[i];
sal_Int32 nMaxIntegral;
if (pMemberRef->eTypeClass == typelib_TypeClass_INTERFACE
|| pMemberRef->eTypeClass == typelib_TypeClass_SEQUENCE)
{
nMaxIntegral = (sal_Int32)(sizeof(void *));
nStructSize = newAlignedSize( nStructSize, nMaxIntegral, nMaxIntegral );
}
else
{
TYPELIB_DANGER_GET( &pMemberType, pMemberRef );
nStructSize = typelib_typedescription_getAlignedUnoSize(
pMemberType, nStructSize, nMaxIntegral );
TYPELIB_DANGER_RELEASE( pMemberType );
}
if( nMaxIntegral > rMaxIntegralTypeSize )
rMaxIntegralTypeSize = nMaxIntegral;
}
#ifdef __m68k__
// Anything that is at least 16 bits wide is aligned on a 16-bit
// boundary on the m68k default abi
sal_Int32 nMaxAlign = (rMaxIntegralTypeSize > 2) ? 2 : rMaxIntegralTypeSize;
nStructSize = (nStructSize + nMaxAlign -1) / nMaxAlign * nMaxAlign;
#else
// Example: A { double; int; } structure has a size of 16 instead of 10. The
// compiler must follow this rule if it is possible to access members in arrays through:
// (Element *)((char *)pArray + sizeof( Element ) * ElementPos)
nStructSize = (nStructSize + rMaxIntegralTypeSize -1)
/ rMaxIntegralTypeSize * rMaxIntegralTypeSize;
#endif
nSize += nStructSize;
}
break;
case typelib_TypeClass_ARRAY:
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescription)->pType );
rMaxIntegralTypeSize = pTD->nSize;
TYPELIB_DANGER_RELEASE( pTD );
nSize = ((typelib_ArrayTypeDescription *)pTypeDescription)->nTotalElements * rMaxIntegralTypeSize;
}
break;
case typelib_TypeClass_SEQUENCE:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( void * ));
break;
case typelib_TypeClass_ANY:
// FEATURE_ANY
nSize = (sal_Int32)(sizeof( uno_Any ));
rMaxIntegralTypeSize = (sal_Int32)(sizeof( void * ));
break;
case typelib_TypeClass_TYPE:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( typelib_TypeDescriptionReference * ));
break;
case typelib_TypeClass_BOOLEAN:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Bool ));
break;
case typelib_TypeClass_CHAR:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Unicode ));
break;
case typelib_TypeClass_STRING:
// FEATURE_STRING
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( rtl_uString * ));
break;
case typelib_TypeClass_FLOAT:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( float ));
break;
case typelib_TypeClass_DOUBLE:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( double ));
break;
case typelib_TypeClass_BYTE:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Int8 ));
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Int16 ));
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Int32 ));
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
nSize = rMaxIntegralTypeSize = (sal_Int32)(sizeof( sal_Int64 ));
break;
case typelib_TypeClass_UNKNOWN:
case typelib_TypeClass_SERVICE:
case typelib_TypeClass_MODULE:
default:
OSL_ENSURE( sal_False, "not convertable type" );
};
}
return newAlignedSize( nOffset, nSize, rMaxIntegralTypeSize );
}
//------------------------------------------------------------------------
namespace {
typelib_TypeDescriptionReference ** copyExceptions(
sal_Int32 count, typelib_TypeDescriptionReference ** source)
{
typelib_TypeDescriptionReference ** p
= new typelib_TypeDescriptionReference *[count];
for (sal_Int32 i = 0; i < count; ++i) {
typelib_typedescriptionreference_acquire(p[i] = source[i]);
}
return p;
}
bool createDerivedInterfaceMemberDescription(
typelib_TypeDescription ** result, rtl::OUString const & name,
typelib_TypeDescriptionReference * baseRef,
typelib_TypeDescription const * base, typelib_TypeDescription * interface,
sal_Int32 index, sal_Int32 position)
{
if (baseRef != 0 && base != 0 && interface != 0) {
switch (base->eTypeClass) {
case typelib_TypeClass_INTERFACE_METHOD:
{
typelib_typedescription_newEmpty(
result, typelib_TypeClass_INTERFACE_METHOD, name.pData);
typelib_InterfaceMethodTypeDescription const * baseMethod
= reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(base);
typelib_InterfaceMethodTypeDescription * newMethod
= reinterpret_cast<
typelib_InterfaceMethodTypeDescription * >(*result);
newMethod->aBase.nPosition = position;
rtl_uString_acquire(
newMethod->aBase.pMemberName
= baseMethod->aBase.pMemberName);
typelib_typedescriptionreference_acquire(
newMethod->pReturnTypeRef = baseMethod->pReturnTypeRef);
newMethod->nParams = baseMethod->nParams;
newMethod->pParams = new typelib_MethodParameter[
newMethod->nParams];
for (sal_Int32 i = 0; i < newMethod->nParams; ++i) {
rtl_uString_acquire(
newMethod->pParams[i].pName
= baseMethod->pParams[i].pName);
typelib_typedescriptionreference_acquire(
newMethod->pParams[i].pTypeRef
= baseMethod->pParams[i].pTypeRef);
newMethod->pParams[i].bIn = baseMethod->pParams[i].bIn;
newMethod->pParams[i].bOut = baseMethod->pParams[i].bOut;
}
newMethod->nExceptions = baseMethod->nExceptions;
newMethod->ppExceptions = copyExceptions(
baseMethod->nExceptions, baseMethod->ppExceptions);
newMethod->bOneWay = baseMethod->bOneWay;
newMethod->pInterface
= reinterpret_cast< typelib_InterfaceTypeDescription * >(
interface);
newMethod->pBaseRef = baseRef;
newMethod->nIndex = index;
return true;
}
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
typelib_typedescription_newEmpty(
result, typelib_TypeClass_INTERFACE_ATTRIBUTE, name.pData);
typelib_InterfaceAttributeTypeDescription const * baseAttribute
= reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(base);
typelib_InterfaceAttributeTypeDescription * newAttribute
= reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >(*result);
newAttribute->aBase.nPosition = position;
rtl_uString_acquire(
newAttribute->aBase.pMemberName
= baseAttribute->aBase.pMemberName);
newAttribute->bReadOnly = baseAttribute->bReadOnly;
typelib_typedescriptionreference_acquire(
newAttribute->pAttributeTypeRef
= baseAttribute->pAttributeTypeRef);
newAttribute->pInterface
= reinterpret_cast< typelib_InterfaceTypeDescription * >(
interface);
newAttribute->pBaseRef = baseRef;
newAttribute->nIndex = index;
newAttribute->nGetExceptions = baseAttribute->nGetExceptions;
newAttribute->ppGetExceptions = copyExceptions(
baseAttribute->nGetExceptions,
baseAttribute->ppGetExceptions);
newAttribute->nSetExceptions = baseAttribute->nSetExceptions;
newAttribute->ppSetExceptions = copyExceptions(
baseAttribute->nSetExceptions,
baseAttribute->ppSetExceptions);
return true;
}
default:
break;
}
}
return false;
}
}
extern "C" void SAL_CALL typelib_typedescription_getByName(
typelib_TypeDescription ** ppRet, rtl_uString * pName )
SAL_THROW_EXTERN_C()
{
if( *ppRet )
{
typelib_typedescription_release( (*ppRet) );
*ppRet = 0;
}
static sal_Bool bInited = sal_False;
TypeDescriptor_Init_Impl &rInit = Init::get();
if( !bInited )
{
// guard against multi thread access
MutexGuard aGuard( rInit.getMutex() );
if( !bInited )
{
// avoid recursion during the next ...new calls
bInited = sal_True;
rtl_uString * pTypeName = 0;
typelib_TypeDescription * pType = 0;
rtl_uString_newFromAscii( &pTypeName, "type" );
typelib_typedescription_new( &pType, typelib_TypeClass_TYPE, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "void" );
typelib_typedescription_new( &pType, typelib_TypeClass_VOID, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "boolean" );
typelib_typedescription_new( &pType, typelib_TypeClass_BOOLEAN, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "char" );
typelib_typedescription_new( &pType, typelib_TypeClass_CHAR, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "byte" );
typelib_typedescription_new( &pType, typelib_TypeClass_BYTE, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "string" );
typelib_typedescription_new( &pType, typelib_TypeClass_STRING, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "short" );
typelib_typedescription_new( &pType, typelib_TypeClass_SHORT, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "unsigned short" );
typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_SHORT, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "long" );
typelib_typedescription_new( &pType, typelib_TypeClass_LONG, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "unsigned long" );
typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_LONG, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "hyper" );
typelib_typedescription_new( &pType, typelib_TypeClass_HYPER, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "unsigned hyper" );
typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_HYPER, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "float" );
typelib_typedescription_new( &pType, typelib_TypeClass_FLOAT, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "double" );
typelib_typedescription_new( &pType, typelib_TypeClass_DOUBLE, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
rtl_uString_newFromAscii( &pTypeName, "any" );
typelib_typedescription_new( &pType, typelib_TypeClass_ANY, pTypeName, 0, 0, 0 );
typelib_typedescription_register( &pType );
typelib_typedescription_release( pType );
rtl_uString_release( pTypeName );
}
}
typelib_TypeDescriptionReference * pTDR = 0;
typelib_typedescriptionreference_getByName( &pTDR, pName );
if( pTDR )
{
{
// guard against multi thread access
MutexGuard aGuard( rInit.getMutex() );
// pTDR->pType->pWeakRef == 0 means that the description is empty
if( pTDR->pType && pTDR->pType->pWeakRef )
{
typelib_typedescription_acquire( pTDR->pType );
*ppRet = pTDR->pType;
}
}
typelib_typedescriptionreference_release( pTDR );
}
if (0 == *ppRet)
{
// check for sequence
OUString const & name = *reinterpret_cast< OUString const * >( &pName );
if (2 < name.getLength() && '[' == name[ 0 ])
{
OUString element_name( name.copy( 2 ) );
typelib_TypeDescription * element_td = 0;
typelib_typedescription_getByName( &element_td, element_name.pData );
if (0 != element_td)
{
typelib_typedescription_new(
ppRet, typelib_TypeClass_SEQUENCE, pName, element_td->pWeakRef, 0, 0 );
// register?
typelib_typedescription_release( element_td );
}
}
if (0 == *ppRet)
{
// Check for derived interface member type:
sal_Int32 i1 = name.lastIndexOf(
rtl::OUString::createFromAscii(":@"));
if (i1 >= 0) {
sal_Int32 i2 = i1 + RTL_CONSTASCII_LENGTH(":@");
sal_Int32 i3 = name.indexOf(',', i2);
if (i3 >= 0) {
sal_Int32 i4 = name.indexOf(':', i3);
if (i4 >= 0) {
typelib_TypeDescriptionReference * pBaseRef = 0;
typelib_TypeDescription * pBase = 0;
typelib_TypeDescription * pInterface = 0;
typelib_typedescriptionreference_getByName(
&pBaseRef, name.copy(0, i1).pData);
if (pBaseRef != 0) {
typelib_typedescriptionreference_getDescription(
&pBase, pBaseRef);
}
typelib_typedescription_getByName(
&pInterface, name.copy(i4 + 1).pData);
if (!createDerivedInterfaceMemberDescription(
ppRet, name, pBaseRef, pBase, pInterface,
name.copy(i2, i3 - i2).toInt32(),
name.copy(i3 + 1, i4 - i3 - 1).toInt32()))
{
if (pInterface != 0) {
typelib_typedescription_release(pInterface);
}
if (pBase != 0) {
typelib_typedescription_release(pBase);
}
if (pBaseRef != 0) {
typelib_typedescriptionreference_release(
pBaseRef);
}
}
}
}
}
}
if (0 == *ppRet)
{
// on demand access
rInit.callChain( ppRet, pName );
}
if( *ppRet )
{
// typedescription found
if (typelib_TypeClass_TYPEDEF == (*ppRet)->eTypeClass)
{
typelib_TypeDescription * pTD = 0;
typelib_typedescriptionreference_getDescription(
&pTD, ((typelib_IndirectTypeDescription *)*ppRet)->pType );
typelib_typedescription_release( *ppRet );
*ppRet = pTD;
}
else
{
// set to on demand
(*ppRet)->bOnDemand = sal_True;
// The type description is hold by the reference until
// on demand is activated.
typelib_typedescription_register( ppRet );
// insert into the chache
MutexGuard aGuard( rInit.getMutex() );
if( !rInit.pCache )
rInit.pCache = new TypeDescriptionList_Impl;
if( (sal_Int32)rInit.pCache->size() >= nCacheSize )
{
typelib_typedescription_release( rInit.pCache->front() );
rInit.pCache->pop_front();
}
// descriptions in the cache must be acquired!
typelib_typedescription_acquire( *ppRet );
rInit.pCache->push_back( *ppRet );
}
}
}
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_newByAsciiName(
typelib_TypeDescriptionReference ** ppTDR,
typelib_TypeClass eTypeClass,
const sal_Char * pTypeName )
SAL_THROW_EXTERN_C()
{
OUString aTypeName( OUString::createFromAscii( pTypeName ) );
typelib_typedescriptionreference_new( ppTDR, eTypeClass, aTypeName.pData );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_new(
typelib_TypeDescriptionReference ** ppTDR,
typelib_TypeClass eTypeClass, rtl_uString * pTypeName )
SAL_THROW_EXTERN_C()
{
TypeDescriptor_Init_Impl &rInit = Init::get();
if( eTypeClass == typelib_TypeClass_TYPEDEF )
{
// on demand access
typelib_TypeDescription * pRet = 0;
rInit.callChain( &pRet, pTypeName );
if( pRet )
{
// typedescription found
if (typelib_TypeClass_TYPEDEF == pRet->eTypeClass)
{
typelib_typedescriptionreference_acquire(
((typelib_IndirectTypeDescription *)pRet)->pType );
if (*ppTDR)
typelib_typedescriptionreference_release( *ppTDR );
*ppTDR = ((typelib_IndirectTypeDescription *)pRet)->pType;
typelib_typedescription_release( pRet );
}
else
{
// set to on demand
pRet->bOnDemand = sal_True;
// The type description is hold by the reference until
// on demand is activated.
typelib_typedescription_register( &pRet );
// insert into the chache
MutexGuard aGuard( rInit.getMutex() );
if( !rInit.pCache )
rInit.pCache = new TypeDescriptionList_Impl;
if( (sal_Int32)rInit.pCache->size() >= nCacheSize )
{
typelib_typedescription_release( rInit.pCache->front() );
rInit.pCache->pop_front();
}
rInit.pCache->push_back( pRet );
// pRet kept acquired for cache
typelib_typedescriptionreference_acquire( pRet->pWeakRef );
if (*ppTDR)
typelib_typedescriptionreference_release( *ppTDR );
*ppTDR = pRet->pWeakRef;
}
}
else if (*ppTDR)
{
#if OSL_DEBUG_LEVEL > 1
OString aStr( OUStringToOString( pTypeName, RTL_TEXTENCODING_ASCII_US ) );
OSL_ENSURE( !"### typedef not found: ", aStr.getStr() );
#endif
typelib_typedescriptionreference_release( *ppTDR );
*ppTDR = 0;
}
return;
}
MutexGuard aGuard( rInit.getMutex() );
typelib_typedescriptionreference_getByName( ppTDR, pTypeName );
if( *ppTDR )
return;
if( reallyWeak( eTypeClass ) )
{
typelib_TypeDescriptionReference * pTDR = new typelib_TypeDescriptionReference();
#if OSL_DEBUG_LEVEL > 1
osl_incrementInterlockedCount( &rInit.nTypeDescriptionReferenceCount );
#endif
pTDR->nRefCount = 1;
pTDR->nStaticRefCount = 0;
pTDR->eTypeClass = eTypeClass;
pTDR->pUniqueIdentifier = 0;
pTDR->pReserved = 0;
rtl_uString_acquire( pTDR->pTypeName = pTypeName );
pTDR->pType = 0;
*ppTDR = pTDR;
}
else
{
typelib_typedescription_newEmpty( (typelib_TypeDescription ** )ppTDR, eTypeClass, pTypeName );
// description will be registered but not acquired
(*(typelib_TypeDescription ** )ppTDR)->bOnDemand = sal_True;
(*(typelib_TypeDescription ** )ppTDR)->bComplete = sal_False;
}
if( !rInit.pWeakMap )
rInit.pWeakMap = new WeakMap_Impl;
// Heavy hack, the const sal_Unicode * is hold by the typedescription reference
// not registered
rInit.pWeakMap->operator[]( (*ppTDR)->pTypeName->buffer ) = *ppTDR;
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_acquire(
typelib_TypeDescriptionReference * pRef )
SAL_THROW_EXTERN_C()
{
::osl_incrementInterlockedCount( &pRef->nRefCount );
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_release(
typelib_TypeDescriptionReference * pRef )
SAL_THROW_EXTERN_C()
{
// Is it a type description?
if( reallyWeak( pRef->eTypeClass ) )
{
if( ! ::osl_decrementInterlockedCount( &pRef->nRefCount ) )
{
TypeDescriptor_Init_Impl &rInit = Init::get();
if( rInit.pWeakMap )
{
MutexGuard aGuard( rInit.getMutex() );
WeakMap_Impl::iterator aIt = rInit.pWeakMap->find( (sal_Unicode*)pRef->pTypeName->buffer );
if( !(aIt == rInit.pWeakMap->end()) && (*aIt).second == pRef )
{
// remove only if it contains the same object
rInit.pWeakMap->erase( aIt );
}
}
rtl_uString_release( pRef->pTypeName );
OSL_ASSERT( pRef->pType == 0 );
#if OSL_DEBUG_LEVEL > 1
osl_decrementInterlockedCount( &rInit.nTypeDescriptionReferenceCount );
#endif
delete pRef;
}
}
else
{
typelib_typedescription_release( (typelib_TypeDescription *)pRef );
}
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_getDescription(
typelib_TypeDescription ** ppRet, typelib_TypeDescriptionReference * pRef )
SAL_THROW_EXTERN_C()
{
if( *ppRet )
{
typelib_typedescription_release( *ppRet );
*ppRet = 0;
}
if( !reallyWeak( pRef->eTypeClass ) && pRef->pType && pRef->pType->pWeakRef )
{
// reference is a description and initialized
osl_incrementInterlockedCount( &((typelib_TypeDescription *)pRef)->nRefCount );
*ppRet = (typelib_TypeDescription *)pRef;
return;
}
{
MutexGuard aGuard( Init::get().getMutex() );
// pRef->pType->pWeakRef == 0 means that the description is empty
if( pRef->pType && pRef->pType->pWeakRef )
{
sal_Int32 n = ::osl_incrementInterlockedCount( &pRef->pType->nRefCount );
if( n > 1 )
{
// The refence is incremented. The object cannot be destroyed.
// Release the guard at the earliest point.
*ppRet = pRef->pType;
return;
}
else
{
::osl_decrementInterlockedCount( &pRef->pType->nRefCount );
// detruction of this type in progress (another thread!)
// no acces through this weak reference
pRef->pType = 0;
}
}
}
typelib_typedescription_getByName( ppRet, pRef->pTypeName );
OSL_ASSERT( !*ppRet || rtl_ustr_compare( pRef->pTypeName->buffer, (*ppRet)->pTypeName->buffer ) == 0 );
OSL_ASSERT( !*ppRet || pRef->eTypeClass == (*ppRet)->eTypeClass );
OSL_ASSERT( !*ppRet || pRef == (*ppRet)->pWeakRef );
pRef->pType = *ppRet;
}
//------------------------------------------------------------------------
extern "C" void SAL_CALL typelib_typedescriptionreference_getByName(
typelib_TypeDescriptionReference ** ppRet, rtl_uString * pName )
SAL_THROW_EXTERN_C()
{
if( *ppRet )
{
typelib_typedescriptionreference_release( *ppRet );
*ppRet = 0;
}
TypeDescriptor_Init_Impl &rInit = Init::get();
if( rInit.pWeakMap )
{
MutexGuard aGuard( rInit.getMutex() );
WeakMap_Impl::const_iterator aIt = rInit.pWeakMap->find( (sal_Unicode*)pName->buffer );
if( !(aIt == rInit.pWeakMap->end()) ) // != failed on msc4.2
{
sal_Int32 n = ::osl_incrementInterlockedCount( &(*aIt).second->nRefCount );
if( n > 1 )
{
// The refence is incremented. The object cannot be destroyed.
// Release the guard at the earliest point.
*ppRet = (*aIt).second;
}
else
{
// detruction of this type in progress (another thread!)
// no acces through this weak reference
::osl_decrementInterlockedCount( &(*aIt).second->nRefCount );
}
}
}
}
//------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL typelib_typedescriptionreference_equals(
const typelib_TypeDescriptionReference * p1,
const typelib_TypeDescriptionReference * p2 )
SAL_THROW_EXTERN_C()
{
return (p1 == p2 ||
(p1->eTypeClass == p2->eTypeClass &&
p1->pTypeName->length == p2->pTypeName->length &&
rtl_ustr_compare( p1->pTypeName->buffer, p2->pTypeName->buffer ) == 0));
}
//##################################################################################################
extern "C" void SAL_CALL typelib_typedescriptionreference_assign(
typelib_TypeDescriptionReference ** ppDest,
typelib_TypeDescriptionReference * pSource )
SAL_THROW_EXTERN_C()
{
if (*ppDest != pSource)
{
::typelib_typedescriptionreference_acquire( pSource );
::typelib_typedescriptionreference_release( *ppDest );
*ppDest = pSource;
}
}
//##################################################################################################
extern "C" void SAL_CALL typelib_setCacheSize( sal_Int32 nNewSize )
SAL_THROW_EXTERN_C()
{
OSL_ENSURE( nNewSize >= 0, "### illegal cache size given!" );
if (nNewSize >= 0)
{
TypeDescriptor_Init_Impl &rInit = Init::get();
MutexGuard aGuard( rInit.getMutex() );
if ((nNewSize < nCacheSize) && rInit.pCache)
{
while ((sal_Int32)rInit.pCache->size() != nNewSize)
{
typelib_typedescription_release( rInit.pCache->front() );
rInit.pCache->pop_front();
}
}
nCacheSize = nNewSize;
}
}
static sal_Bool s_aAssignableFromTab[11][11] =
{
/* from CH,BO,BY,SH,US,LO,UL,HY,UH,FL,DO */
/* TypeClass_CHAR */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TypeClass_BOOLEAN */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TypeClass_BYTE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TypeClass_SHORT */ { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
/* TypeClass_UNSIGNED_SHORT */ { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
/* TypeClass_LONG */ { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
/* TypeClass_UNSIGNED_LONG */ { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
/* TypeClass_HYPER */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
/* TypeClass_UNSIGNED_HYPER */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
/* TypeClass_FLOAT */ { 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0 },
/* TypeClass_DOUBLE */ { 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1 }
};
//##################################################################################################
extern "C" sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom(
typelib_TypeDescriptionReference * pAssignable,
typelib_TypeDescriptionReference * pFrom )
SAL_THROW_EXTERN_C()
{
if (pAssignable && pFrom)
{
typelib_TypeClass eAssignable = pAssignable->eTypeClass;
typelib_TypeClass eFrom = pFrom->eTypeClass;
if (eAssignable == typelib_TypeClass_ANY) // anything can be assigned to an any .)
return sal_True;
if (eAssignable == eFrom)
{
if (type_equals( pAssignable, pFrom )) // first shot
{
return sal_True;
}
else
{
switch (eAssignable)
{
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
{
typelib_TypeDescription * pFromDescr = 0;
TYPELIB_DANGER_GET( &pFromDescr, pFrom );
if (! ((typelib_CompoundTypeDescription *)pFromDescr)->pBaseTypeDescription)
{
TYPELIB_DANGER_RELEASE( pFromDescr );
return sal_False;
}
sal_Bool bRet = typelib_typedescriptionreference_isAssignableFrom(
pAssignable,
((typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pFromDescr)->pBaseTypeDescription)->pWeakRef );
TYPELIB_DANGER_RELEASE( pFromDescr );
return bRet;
}
case typelib_TypeClass_INTERFACE:
{
typelib_TypeDescription * pFromDescr = 0;
TYPELIB_DANGER_GET( &pFromDescr, pFrom );
typelib_InterfaceTypeDescription * pFromIfc
= reinterpret_cast<
typelib_InterfaceTypeDescription * >(pFromDescr);
bool bRet = false;
for (sal_Int32 i = 0; i < pFromIfc->nBaseTypes; ++i) {
if (typelib_typedescriptionreference_isAssignableFrom(
pAssignable,
pFromIfc->ppBaseTypes[i]->aBase.pWeakRef))
{
bRet = true;
break;
}
}
TYPELIB_DANGER_RELEASE( pFromDescr );
return bRet;
}
default:
{
return sal_False;
}
}
}
}
return (eAssignable >= typelib_TypeClass_CHAR && eAssignable <= typelib_TypeClass_DOUBLE &&
eFrom >= typelib_TypeClass_CHAR && eFrom <= typelib_TypeClass_DOUBLE &&
s_aAssignableFromTab[eAssignable-1][eFrom-1]);
}
return sal_False;
}
//##################################################################################################
extern "C" sal_Bool SAL_CALL typelib_typedescription_isAssignableFrom(
typelib_TypeDescription * pAssignable,
typelib_TypeDescription * pFrom )
SAL_THROW_EXTERN_C()
{
return typelib_typedescriptionreference_isAssignableFrom(
pAssignable->pWeakRef, pFrom->pWeakRef );
}
//##################################################################################################
extern "C" sal_Bool SAL_CALL typelib_typedescription_complete(
typelib_TypeDescription ** ppTypeDescr )
SAL_THROW_EXTERN_C()
{
return complete(ppTypeDescr, true);
}