diff options
Diffstat (limited to 'cppu/source/typelib/typelib.cxx')
-rw-r--r-- | cppu/source/typelib/typelib.cxx | 2660 |
1 files changed, 2660 insertions, 0 deletions
diff --git a/cppu/source/typelib/typelib.cxx b/cppu/source/typelib/typelib.cxx new file mode 100644 index 000000000000..aa0d18589a89 --- /dev/null +++ b/cppu/source/typelib/typelib.cxx @@ -0,0 +1,2660 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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; + } +#if OSL_DEBUG_LEVEL > 1 + OSL_ASSERT( nTypeDescriptionCount == 0 ); + OSL_ASSERT( nCompoundTypeDescriptionCount == 0 ); + OSL_ASSERT( nUnionTypeDescriptionCount == 0 ); + OSL_ASSERT( nIndirectTypeDescriptionCount == 0 ); + OSL_ASSERT( nArrayTypeDescriptionCount == 0 ); + OSL_ASSERT( nEnumTypeDescriptionCount == 0 ); + OSL_ASSERT( nInterfaceMethodTypeDescriptionCount == 0 ); + OSL_ASSERT( nInterfaceAttributeTypeDescriptionCount == 0 ); + OSL_ASSERT( nInterfaceTypeDescriptionCount == 0 ); + OSL_ASSERT( nTypeDescriptionReferenceCount == 0 ); + + OSL_ASSERT( !pCallbacks || pCallbacks->empty() ); +#endif + 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); +} |