diff options
Diffstat (limited to '')
-rw-r--r-- | cppu/source/typelib/static_types.cxx | 555 | ||||
-rw-r--r-- | cppu/source/typelib/typelib.cxx | 2399 | ||||
-rw-r--r-- | cppu/source/typelib/typelib.hxx | 45 |
3 files changed, 2999 insertions, 0 deletions
diff --git a/cppu/source/typelib/static_types.cxx b/cppu/source/typelib/static_types.cxx new file mode 100644 index 000000000..6b9a35ac9 --- /dev/null +++ b/cppu/source/typelib/static_types.cxx @@ -0,0 +1,555 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <algorithm> +#include <cassert> + +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> + +#include <typelib/typedescription.h> +#include "typelib.hxx" + + +using namespace osl; + +namespace +{ + Mutex& typelib_StaticInitMutex() + { + static Mutex SINGLETON; + return SINGLETON; + } +} + +extern "C" +{ + + +#ifdef _WIN32 +#pragma pack(push, 8) +#endif + +namespace { + +/** + * The double member determines the alignment. + * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ). + * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type + * determines the alignment. + */ +struct AlignSize_Impl +{ + sal_Int16 nInt16; +#ifdef AIX + //double: doubleword aligned if -qalign=natural/-malign=natural + //which isn't the default ABI. Otherwise word aligned, While a long long int + //is always doubleword aligned, so use that instead. + sal_Int64 dDouble; +#else + double dDouble; +#endif +}; + +} + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +// the value of the maximal alignment +const sal_Int32 nMaxAlignment = static_cast<sal_Int32>( reinterpret_cast<sal_Size>(&reinterpret_cast<AlignSize_Impl *>(16)->dDouble) - 16); + +static sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment ) +{ + if( nRequestedAlignment > nMaxAlignment ) + nRequestedAlignment = nMaxAlignment; + return nRequestedAlignment; +} + +/** + * Calculate the new size of the struktur. + */ +static sal_Int32 newAlignedSize( + sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment ) +{ + NeededAlignment = adjustAlignment( NeededAlignment ); + return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize; +} + + +// !for NOT REALLY WEAK TYPES only! +static typelib_TypeDescriptionReference * igetTypeByName( rtl_uString const * pTypeName ) +{ + typelib_TypeDescriptionReference * pRef = nullptr; + ::typelib_typedescriptionreference_getByName( &pRef, pTypeName ); + if (pRef && pRef->pType && pRef->pType->pWeakRef) // found initialized td + { + return pRef; + } + return nullptr; +} + +extern "C" +{ + +typelib_TypeDescriptionReference ** SAL_CALL typelib_static_type_getByTypeClass( + typelib_TypeClass eTypeClass ) + SAL_THROW_EXTERN_C() +{ + static typelib_TypeDescriptionReference * s_aTypes[] = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr }; + + if (! s_aTypes[eTypeClass]) + { + MutexGuard aGuard( typelib_StaticInitMutex() ); + if (! s_aTypes[eTypeClass]) + { + static const char * s_aTypeNames[] = { + "void", "char", "boolean", "byte", + "short", "unsigned short", "long", "unsigned long", + "hyper", "unsigned hyper", "float", "double", + "string", "type", "any" }; + + switch (eTypeClass) + { + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_INTERFACE: + { + // type + if (! s_aTypes[typelib_TypeClass_TYPE]) + { + OUString sTypeName("type"); + ::typelib_typedescriptionreference_new( + &s_aTypes[typelib_TypeClass_TYPE], typelib_TypeClass_TYPE, sTypeName.pData ); + // another static ref: + ++s_aTypes[typelib_TypeClass_TYPE]->nStaticRefCount; + } + // any + if (! s_aTypes[typelib_TypeClass_ANY]) + { + OUString sTypeName("any"); + ::typelib_typedescriptionreference_new( + &s_aTypes[typelib_TypeClass_ANY], typelib_TypeClass_ANY, sTypeName.pData ); + // another static ref: + ++s_aTypes[typelib_TypeClass_ANY]->nStaticRefCount; + } + // string + if (! s_aTypes[typelib_TypeClass_STRING]) + { + OUString sTypeName("string"); + ::typelib_typedescriptionreference_new( + &s_aTypes[typelib_TypeClass_STRING], typelib_TypeClass_STRING, sTypeName.pData ); + // another static ref: + ++s_aTypes[typelib_TypeClass_STRING]->nStaticRefCount; + } + // XInterface + if (! s_aTypes[typelib_TypeClass_INTERFACE]) + { + OUString sTypeName("com.sun.star.uno.XInterface"); + + typelib_InterfaceTypeDescription * pTD = nullptr; + + typelib_TypeDescriptionReference * pMembers[3] = { nullptr,nullptr,nullptr }; + OUString sMethodName0("com.sun.star.uno.XInterface::queryInterface"); + ::typelib_typedescriptionreference_new( + &pMembers[0], typelib_TypeClass_INTERFACE_METHOD, sMethodName0.pData ); + OUString sMethodName1("com.sun.star.uno.XInterface::acquire"); + ::typelib_typedescriptionreference_new( + &pMembers[1], typelib_TypeClass_INTERFACE_METHOD, sMethodName1.pData ); + OUString sMethodName2("com.sun.star.uno.XInterface::release"); + ::typelib_typedescriptionreference_new( + &pMembers[2], typelib_TypeClass_INTERFACE_METHOD, sMethodName2.pData ); + + ::typelib_typedescription_newInterface( + &pTD, sTypeName.pData, 0, 0, 0, 0, 0, nullptr, 3, pMembers ); + + ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription **>(&pTD) ); + s_aTypes[typelib_TypeClass_INTERFACE] = pTD->aBase.pWeakRef; + ::typelib_typedescriptionreference_acquire( + s_aTypes[typelib_TypeClass_INTERFACE] ); + // another static ref: + ++s_aTypes[typelib_TypeClass_INTERFACE]->nStaticRefCount; + ::typelib_typedescription_release( &pTD->aBase ); + + ::typelib_typedescriptionreference_release( pMembers[0] ); + ::typelib_typedescriptionreference_release( pMembers[1] ); + ::typelib_typedescriptionreference_release( pMembers[2] ); + // Exception + assert( ! s_aTypes[typelib_TypeClass_EXCEPTION] ); + { + typelib_TypeDescription * pTD1 = nullptr; + OUString sTypeName1("com.sun.star.uno.Exception"); + + typelib_CompoundMember_Init aMembers[2]; + OUString sMemberType0("string"); + OUString sMemberName0("Message"); + aMembers[0].eTypeClass = typelib_TypeClass_STRING; + aMembers[0].pTypeName = sMemberType0.pData; + aMembers[0].pMemberName = sMemberName0.pData; + OUString sMemberType1("com.sun.star.uno.XInterface"); + OUString sMemberName1("Context"); + aMembers[1].eTypeClass = typelib_TypeClass_INTERFACE; + aMembers[1].pTypeName = sMemberType1.pData; + aMembers[1].pMemberName = sMemberName1.pData; + + ::typelib_typedescription_new( + &pTD1, typelib_TypeClass_EXCEPTION, sTypeName1.pData, nullptr, 2, aMembers ); + typelib_typedescription_register( &pTD1 ); + s_aTypes[typelib_TypeClass_EXCEPTION] = pTD1->pWeakRef; + typelib_typedescriptionreference_acquire( + s_aTypes[typelib_TypeClass_EXCEPTION]); + // another static ref: + ++s_aTypes[typelib_TypeClass_EXCEPTION]->nStaticRefCount; + // RuntimeException + OUString sTypeName2("com.sun.star.uno.RuntimeException"); + ::typelib_typedescription_new( + &pTD1, typelib_TypeClass_EXCEPTION, sTypeName2.pData, s_aTypes[typelib_TypeClass_EXCEPTION], 0, nullptr ); + ::typelib_typedescription_register( &pTD1 ); + ::typelib_typedescription_release( pTD1 ); + } + // XInterface members + typelib_InterfaceMethodTypeDescription * pMethod = nullptr; + typelib_Parameter_Init aParameters[1]; + OUString sParamName0("aType"); + OUString sParamType0("type"); + aParameters[0].pParamName = sParamName0.pData; + aParameters[0].eTypeClass = typelib_TypeClass_TYPE; + aParameters[0].pTypeName = sParamType0.pData; + aParameters[0].bIn = true; + aParameters[0].bOut = false; + rtl_uString * pExceptions[1]; + OUString sExceptionName0("com.sun.star.uno.RuntimeException"); + pExceptions[0] = sExceptionName0.pData; + OUString sReturnType0("any"); + typelib_typedescription_newInterfaceMethod( + &pMethod, 0, false, sMethodName0.pData, + typelib_TypeClass_ANY, sReturnType0.pData, + 1, aParameters, 1, pExceptions ); + ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) ); + + OUString sReturnType1("void"); + ::typelib_typedescription_newInterfaceMethod( + &pMethod, 1, true, sMethodName1.pData, + typelib_TypeClass_VOID, sReturnType1.pData, 0, nullptr, 0, nullptr ); + ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) ); + + ::typelib_typedescription_newInterfaceMethod( + &pMethod, 2, true, sMethodName2.pData, + typelib_TypeClass_VOID, sReturnType1.pData, + 0, nullptr, 0, nullptr ); + ::typelib_typedescription_register( reinterpret_cast<typelib_TypeDescription**>(&pMethod) ); + ::typelib_typedescription_release( &pMethod->aBase.aBase ); + } + break; + } + default: + { + OUString aTypeName( OUString::createFromAscii( s_aTypeNames[eTypeClass] ) ); + ::typelib_typedescriptionreference_new( &s_aTypes[eTypeClass], eTypeClass, aTypeName.pData ); + // another static ref: + ++s_aTypes[eTypeClass]->nStaticRefCount; + } + } + } + } + return &s_aTypes[eTypeClass]; +} + +void SAL_CALL typelib_static_type_init( + typelib_TypeDescriptionReference ** ppRef, + typelib_TypeClass eTypeClass, const char * pTypeName ) + SAL_THROW_EXTERN_C() +{ + if (! *ppRef) + { + MutexGuard aGuard( typelib_StaticInitMutex() ); + if (! *ppRef) + { + OUString aTypeName( OUString::createFromAscii( pTypeName ) ); + ::typelib_typedescriptionreference_new( ppRef, eTypeClass, aTypeName.pData ); + + assert(*ppRef && "coverity[var_deref_op] - shouldn't be possible"); + ++((*ppRef)->nStaticRefCount); + } + } +} + +void SAL_CALL typelib_static_sequence_type_init( + typelib_TypeDescriptionReference ** ppRef, + typelib_TypeDescriptionReference * pElementType ) + SAL_THROW_EXTERN_C() +{ + if ( *ppRef) + return; + + MutexGuard aGuard( typelib_StaticInitMutex() ); + if ( *ppRef) + return; + + OUString aTypeName = "[]" + OUString::unacquired(&pElementType->pTypeName); + + static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_SEQUENCE) ); + *ppRef = igetTypeByName( aTypeName.pData ); + if (!*ppRef) + { + typelib_TypeDescription * pReg = nullptr; + ::typelib_typedescription_new( + &pReg, typelib_TypeClass_SEQUENCE, + aTypeName.pData, pElementType, 0, nullptr ); + + ::typelib_typedescription_register( &pReg ); + *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + assert( *ppRef == pReg->pWeakRef ); + } + // another static ref: + ++((*ppRef)->nStaticRefCount); +} + + +namespace { + +void init( + typelib_TypeDescriptionReference ** ppRef, + typelib_TypeClass eTypeClass, const char * pTypeName, + typelib_TypeDescriptionReference * pBaseType, + sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers, + sal_Bool const * pParameterizedTypes) +{ + assert( eTypeClass == typelib_TypeClass_STRUCT || eTypeClass == typelib_TypeClass_EXCEPTION ); + + if ( *ppRef) + return; + + MutexGuard aGuard( typelib_StaticInitMutex() ); + if ( *ppRef) + return; + + assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(eTypeClass) ); + OUString aTypeName( OUString::createFromAscii( pTypeName ) ); + *ppRef = igetTypeByName( aTypeName.pData ); + if (!*ppRef) + { + typelib_CompoundTypeDescription * pComp = nullptr; + ::typelib_typedescription_newEmpty( + reinterpret_cast<typelib_TypeDescription **>(&pComp), eTypeClass, aTypeName.pData ); + + sal_Int32 nOffset = 0; + if (pBaseType) + { + ::typelib_typedescriptionreference_getDescription( + reinterpret_cast<typelib_TypeDescription **>(&pComp->pBaseTypeDescription), pBaseType ); + assert( pComp->pBaseTypeDescription ); + nOffset = pComp->pBaseTypeDescription->aBase.nSize; + assert( newAlignedSize( 0, pComp->pBaseTypeDescription->aBase.nSize, pComp->pBaseTypeDescription->aBase.nAlignment ) == pComp->pBaseTypeDescription->aBase.nSize ); // unexpected offset + } + + if (nMembers) + { + pComp->nMembers = nMembers; + pComp->pMemberOffsets = new sal_Int32[ nMembers ]; + pComp->ppTypeRefs = new typelib_TypeDescriptionReference *[ nMembers ]; + if (pParameterizedTypes != nullptr) { + reinterpret_cast< typelib_StructTypeDescription * >( + pComp)->pParameterizedTypes + = new sal_Bool[nMembers]; + } + for ( sal_Int32 i = 0 ; i < nMembers; ++i ) + { + pComp->ppTypeRefs[i] = ppMembers[i]; + ::typelib_typedescriptionreference_acquire( + pComp->ppTypeRefs[i] ); + // write offset + typelib_TypeDescription * pTD = nullptr; + TYPELIB_DANGER_GET( &pTD, pComp->ppTypeRefs[i] ); + assert( pTD->nSize ); // void member? + nOffset = newAlignedSize( nOffset, pTD->nSize, pTD->nAlignment ); + pComp->pMemberOffsets[i] = nOffset - pTD->nSize; + TYPELIB_DANGER_RELEASE( pTD ); + + if (pParameterizedTypes != nullptr) { + reinterpret_cast< typelib_StructTypeDescription * >( + pComp)->pParameterizedTypes[i] + = pParameterizedTypes[i]; + } + } + } + + typelib_TypeDescription * pReg = &pComp->aBase; + pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + // sizeof(void) not allowed + pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment ); + pReg->nAlignment = adjustAlignment( pReg->nAlignment ); + pReg->bComplete = false; + + ::typelib_typedescription_register( &pReg ); + *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + assert( *ppRef == pReg->pWeakRef ); + } + // another static ref: + ++((*ppRef)->nStaticRefCount); +} + +} + +void SAL_CALL typelib_static_compound_type_init( + typelib_TypeDescriptionReference ** ppRef, + typelib_TypeClass eTypeClass, const char * pTypeName, + typelib_TypeDescriptionReference * pBaseType, + sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers ) + SAL_THROW_EXTERN_C() +{ + init(ppRef, eTypeClass, pTypeName, pBaseType, nMembers, ppMembers, nullptr); +} + +void SAL_CALL typelib_static_struct_type_init( + typelib_TypeDescriptionReference ** ppRef, const char * pTypeName, + typelib_TypeDescriptionReference * pBaseType, + sal_Int32 nMembers, typelib_TypeDescriptionReference ** ppMembers, + sal_Bool const * pParameterizedTypes ) + SAL_THROW_EXTERN_C() +{ + init( + ppRef, typelib_TypeClass_STRUCT, pTypeName, pBaseType, nMembers, + ppMembers, pParameterizedTypes); +} + +void SAL_CALL typelib_static_interface_type_init( + typelib_TypeDescriptionReference ** ppRef, + const char * pTypeName, + typelib_TypeDescriptionReference * pBaseType ) + SAL_THROW_EXTERN_C() +{ + // coverity[callee_ptr_arith] - not a bug + typelib_static_mi_interface_type_init( + ppRef, pTypeName, pBaseType == nullptr ? 0 : 1, &pBaseType); +} + +void SAL_CALL typelib_static_mi_interface_type_init( + typelib_TypeDescriptionReference ** ppRef, + const char * pTypeName, + sal_Int32 nBaseTypes, + typelib_TypeDescriptionReference ** ppBaseTypes ) + SAL_THROW_EXTERN_C() +{ + if ( *ppRef) + return; + + MutexGuard aGuard( typelib_StaticInitMutex() ); + if ( *ppRef) + return; + + static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_INTERFACE) ); + OUString aTypeName( OUString::createFromAscii( pTypeName ) ); + *ppRef = igetTypeByName( aTypeName.pData ); + if (!*ppRef) + { + typelib_InterfaceTypeDescription * pIface = nullptr; + ::typelib_typedescription_newEmpty( + reinterpret_cast<typelib_TypeDescription **>(&pIface), typelib_TypeClass_INTERFACE, aTypeName.pData ); + + pIface->nBaseTypes = std::max< sal_Int32 >(nBaseTypes, 1); + pIface->ppBaseTypes = new typelib_InterfaceTypeDescription *[ + pIface->nBaseTypes]; + if (nBaseTypes > 0) + { + for (sal_Int32 i = 0; i < nBaseTypes; ++i) { + pIface->ppBaseTypes[i] = nullptr; + ::typelib_typedescriptionreference_getDescription( + reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[i]), ppBaseTypes[i] ); + assert( pIface->ppBaseTypes[i] ); + } + } + else + { + pIface->ppBaseTypes[0] = nullptr; + ::typelib_typedescriptionreference_getDescription( + reinterpret_cast<typelib_TypeDescription **>(&pIface->ppBaseTypes[0]), + * ::typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ) ); + assert( pIface->ppBaseTypes[0] ); + } + pIface->pBaseTypeDescription = pIface->ppBaseTypes[0]; + typelib_typedescription_acquire( + &pIface->pBaseTypeDescription->aBase); + + typelib_TypeDescription * pReg = &pIface->aBase; + pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + // sizeof(void) not allowed + pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment ); + + pReg->nAlignment = adjustAlignment( pReg->nAlignment ); + pReg->bComplete = false; + + ::typelib_typedescription_register( &pReg ); + *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + assert( *ppRef == pReg->pWeakRef ); + } + // another static ref: + ++((*ppRef)->nStaticRefCount); +} + + +void SAL_CALL typelib_static_enum_type_init( + typelib_TypeDescriptionReference ** ppRef, + const char * pTypeName, + sal_Int32 nDefaultValue ) + SAL_THROW_EXTERN_C() +{ + if ( *ppRef) + return; + + MutexGuard aGuard( typelib_StaticInitMutex() ); + if ( *ppRef) + return; + + static_assert( ! TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM) ); + OUString aTypeName( OUString::createFromAscii( pTypeName ) ); + *ppRef = igetTypeByName( aTypeName.pData ); + if (!*ppRef) + { + typelib_TypeDescription * pReg = nullptr; + ::typelib_typedescription_newEmpty( + &pReg, typelib_TypeClass_ENUM, aTypeName.pData ); + typelib_EnumTypeDescription * pEnum = reinterpret_cast<typelib_EnumTypeDescription *>(pReg); + + pEnum->nDefaultEnumValue = nDefaultValue; + + pReg->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + // sizeof(void) not allowed + pReg->nSize = ::typelib_typedescription_getAlignedUnoSize( pReg, 0, pReg->nAlignment ); + pReg->nAlignment = ::adjustAlignment( pReg->nAlignment ); + pReg->bComplete = false; + + ::typelib_typedescription_register( &pReg ); + *ppRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pReg); + assert( *ppRef == pReg->pWeakRef ); + } + // another static ref: + ++((*ppRef)->nStaticRefCount); +} + +} // extern "C" + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cppu/source/typelib/typelib.cxx b/cppu/source/typelib/typelib.cxx new file mode 100644 index 000000000..293b4e324 --- /dev/null +++ b/cppu/source/typelib/typelib.cxx @@ -0,0 +1,2399 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + + +#include <algorithm> +#include <unordered_map> +#include <cassert> +#include <list> +#include <set> +#include <utility> +#include <vector> + +#include <stdlib.h> +#include <string.h> +#include <sal/log.hxx> +#include <osl/interlck.h> +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> +#include <typelib/typedescription.h> +#include <uno/any2.h> +#include <o3tl/string_view.hxx> +#include "typelib.hxx" + +using namespace osl; + +#ifdef _WIN32 +#pragma pack(push, 8) +#endif + +namespace { + +/** + * The double member determines the alignment. + * Under OS2 and MS-Windows the Alignment is min( 8, sizeof( type ) ). + * The alignment of a structure is min( 8, sizeof( max basic type ) ), the greatest basic type + * determines the alignment. + */ +struct AlignSize_Impl +{ + sal_Int16 nInt16; +#ifdef AIX + //double: doubleword aligned if -qalign=natural/-malign=natural + //which isn't the default ABI. Otherwise word aligned, While a long long int + //is always doubleword aligned, so use that instead. + sal_Int64 dDouble; +#else + double dDouble; +#endif +}; + +} + +#ifdef _WIN32 +#pragma pack(pop) +#endif + +// the value of the maximal alignment +const sal_Int32 nMaxAlignment = static_cast<sal_Int32>( reinterpret_cast<sal_Size>(&reinterpret_cast<AlignSize_Impl *>(16)->dDouble) - 16); + +static sal_Int32 adjustAlignment( sal_Int32 nRequestedAlignment ) +{ + if( nRequestedAlignment > nMaxAlignment ) + nRequestedAlignment = nMaxAlignment; + return nRequestedAlignment; +} + +/** + * Calculate the new size of the structure. + */ +static sal_Int32 newAlignedSize( + sal_Int32 OldSize, sal_Int32 ElementSize, sal_Int32 NeededAlignment ) +{ + NeededAlignment = adjustAlignment( NeededAlignment ); + return (OldSize + NeededAlignment -1) / NeededAlignment * NeededAlignment + ElementSize; +} + +static sal_Int32 getDescriptionSize( typelib_TypeClass eTypeClass ) +{ + OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass ); + + sal_Int32 nSize; + // The reference is the description + // if the description is empty, then it must be filled with + // the new description + switch( eTypeClass ) + { + case typelib_TypeClass_SEQUENCE: + nSize = sal_Int32(sizeof( typelib_IndirectTypeDescription )); + 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; +} + +namespace { + +struct equalStr_Impl +{ + bool operator()(const sal_Unicode * const & s1, const sal_Unicode * const & s2) const + { return 0 == rtl_ustr_compare( s1, s2 ); } +}; + + +struct hashStr_Impl +{ + size_t operator()(const sal_Unicode * const & s) const + { return rtl_ustr_hashCode( s ); } +}; + +} + +// Heavy hack, the const sal_Unicode * is hold by the typedescription reference +typedef std::unordered_map< const sal_Unicode *, typelib_TypeDescriptionReference *, + hashStr_Impl, equalStr_Impl > WeakMap_Impl; + +typedef std::pair< void *, typelib_typedescription_Callback > CallbackEntry; +typedef std::list< CallbackEntry > CallbackSet_Impl; +typedef std::list< typelib_TypeDescription * > TypeDescriptionList_Impl; + +// # of cached elements +constexpr auto nCacheSize = 256; + +namespace { + +struct TypeDescriptor_Init_Impl +{ + // all type description references + WeakMap_Impl maWeakMap; + // all type description callbacks + CallbackSet_Impl maCallbacks; + // A cache to hold descriptions + TypeDescriptionList_Impl maCache; + // The mutex to guard all type library accesses + Mutex maMutex; + + inline void callChain( typelib_TypeDescription ** ppRet, rtl_uString * pName ); + +#if OSL_DEBUG_LEVEL > 0 + // only for debugging + sal_Int32 nTypeDescriptionCount = 0; + sal_Int32 nCompoundTypeDescriptionCount = 0; + sal_Int32 nIndirectTypeDescriptionCount = 0; + sal_Int32 nEnumTypeDescriptionCount = 0; + sal_Int32 nInterfaceMethodTypeDescriptionCount = 0; + sal_Int32 nInterfaceAttributeTypeDescriptionCount = 0; + sal_Int32 nInterfaceTypeDescriptionCount = 0; + sal_Int32 nTypeDescriptionReferenceCount = 0; +#endif + + TypeDescriptor_Init_Impl() = default; + + ~TypeDescriptor_Init_Impl(); +}; + +} + +inline void TypeDescriptor_Init_Impl::callChain( + typelib_TypeDescription ** ppRet, rtl_uString * pName ) +{ + assert(ppRet != nullptr); + assert(*ppRet == nullptr); + for( const CallbackEntry & rEntry : maCallbacks ) + { + (*rEntry.second)( rEntry.first, ppRet, pName ); + if( *ppRet ) + return; + } +} + + +TypeDescriptor_Init_Impl::~TypeDescriptor_Init_Impl() +{ + for( typelib_TypeDescription* pItem : maCache ) + { + typelib_typedescription_release( pItem ); + } + + { + std::vector< typelib_TypeDescriptionReference * > ppTDR; + ppTDR.reserve( maWeakMap.size() ); + + // save all weak references + for( const auto& rEntry : maWeakMap ) + { + ppTDR.push_back( rEntry.second ); + typelib_typedescriptionreference_acquire( ppTDR.back() ); + } + + for( typelib_TypeDescriptionReference * pTDR : ppTDR ) + { + OSL_ASSERT( pTDR->nRefCount > pTDR->nStaticRefCount ); + pTDR->nRefCount -= pTDR->nStaticRefCount; + + if( pTDR->pType && !pTDR->pType->bOnDemand ) + { + pTDR->pType->bOnDemand = true; + typelib_typedescription_release( pTDR->pType ); + } + typelib_typedescriptionreference_release( pTDR ); + } + +#if defined SAL_LOG_INFO + for( const auto& rEntry : maWeakMap ) + { + typelib_TypeDescriptionReference * pTDR = rEntry.second; + if (pTDR) + { + OString aTypeName( OUStringToOString( OUString::unacquired(&pTDR->pTypeName), RTL_TEXTENCODING_ASCII_US ) ); + SAL_INFO("cppu.typelib", "remaining type: " << aTypeName << "; ref count = " << pTDR->nRefCount); + } + else + { + SAL_INFO("cppu.typelib", "remaining null type entry!?"); + } + } +#endif + } +#if OSL_DEBUG_LEVEL > 0 + SAL_INFO_IF( nTypeDescriptionCount, "cppu.typelib", "nTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nCompoundTypeDescriptionCount, "cppu.typelib", "nCompoundTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nIndirectTypeDescriptionCount, "cppu.typelib", "nIndirectTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nEnumTypeDescriptionCount, "cppu.typelib", "nEnumTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nInterfaceMethodTypeDescriptionCount, "cppu.typelib", "nInterfaceMethodTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nInterfaceAttributeTypeDescriptionCount, "cppu.typelib", "nInterfaceAttributeTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nInterfaceTypeDescriptionCount, "cppu.typelib", "nInterfaceTypeDescriptionCount is not zero" ); + SAL_INFO_IF( nTypeDescriptionReferenceCount, "cppu.typelib", "nTypeDescriptionReferenceCount is not zero" ); +#endif + + SAL_INFO_IF( !maCallbacks.empty(), "cppu.typelib", "pCallbacks is not NULL or empty" ); +}; + +namespace { +TypeDescriptor_Init_Impl& Init() +{ + static TypeDescriptor_Init_Impl SINGLETON; + return SINGLETON; +} +} + +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(); +// OslGuard aGuard( rInit.getMutex() ); + rInit.maCallbacks.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(); + { + // todo mt safe: guard is no solution, can not acquire while calling callback! +// OslGuard aGuard( rInit.getMutex() ); + CallbackEntry aEntry( pContext, pCallback ); + rInit.maCallbacks.erase(std::remove(rInit.maCallbacks.begin(), rInit.maCallbacks.end(), aEntry), + rInit.maCallbacks.end()); + } +} + +static void typelib_typedescription_initTables( + typelib_TypeDescription * pTD ) +{ + typelib_InterfaceTypeDescription * pITD = reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD); + + std::vector<bool> aReadWriteAttributes(pITD->nAllMembers); + for ( sal_Int32 i = pITD->nAllMembers; i--; ) + { + aReadWriteAttributes[i] = false; + if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pITD->ppAllMembers[i]->eTypeClass ) + { + typelib_TypeDescription * pM = nullptr; + TYPELIB_DANGER_GET( &pM, pITD->ppAllMembers[i] ); + OSL_ASSERT( pM ); + if (pM) + { + aReadWriteAttributes[i] = !reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(pM)->bReadOnly; + TYPELIB_DANGER_RELEASE( pM ); + } + else + { + SAL_INFO( "cppu.typelib", "cannot get attribute type description: " << pITD->ppAllMembers[i]->pTypeName ); + } + } + } + + MutexGuard aGuard( Init().maMutex ); + if( pTD->bComplete ) + return; + + // 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 (aReadWriteAttributes[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 (aReadWriteAttributes[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 = true; +} + +namespace { + +template<typename T> T * allocTypeDescription() { + return reinterpret_cast<T *>(new char[sizeof (T)]); +} + +void freeTypeDescription(typelib_TypeDescription const * desc) { + delete[] reinterpret_cast<char const *>(desc); +} + +// 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) + return true; + + OSL_ASSERT( (typelib_TypeClass_STRUCT == (*ppTypeDescr)->eTypeClass || + typelib_TypeClass_EXCEPTION == (*ppTypeDescr)->eTypeClass || + typelib_TypeClass_ENUM == (*ppTypeDescr)->eTypeClass || + typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass) && + !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppTypeDescr)->eTypeClass ) ); + + if (typelib_TypeClass_INTERFACE == (*ppTypeDescr)->eTypeClass && + reinterpret_cast<typelib_InterfaceTypeDescription *>(*ppTypeDescr)->ppAllMembers) + { + if (initTables) { + typelib_typedescription_initTables( *ppTypeDescr ); + } + return true; + } + + typelib_TypeDescription * pTD = nullptr; + // on demand access of complete td + TypeDescriptor_Init_Impl &rInit = Init(); + rInit.callChain( &pTD, (*ppTypeDescr)->pTypeName ); + if (pTD) + { + if (typelib_TypeClass_TYPEDEF == pTD->eTypeClass) + { + typelib_typedescriptionreference_getDescription( + &pTD, reinterpret_cast<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 = true; + + if (pTD->eTypeClass == typelib_TypeClass_INTERFACE + && !pTD->bComplete && initTables) + { + // mandatory info from callback chain + OSL_ASSERT( reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD)->ppAllMembers ); + // complete except of tables init + typelib_typedescription_initTables( pTD ); + pTD->bComplete = 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 cache + MutexGuard aGuard( rInit.maMutex ); + if( rInit.maCache.size() >= nCacheSize ) + { + typelib_typedescription_release( rInit.maCache.front() ); + rInit.maCache.pop_front(); + } + // descriptions in the cache must be acquired! + typelib_typedescription_acquire( pTD ); + rInit.maCache.push_back( pTD ); + + OSL_ASSERT( + pTD->bComplete + || (pTD->eTypeClass == typelib_TypeClass_INTERFACE + && !initTables)); + + ::typelib_typedescription_release( *ppTypeDescr ); + *ppTypeDescr = pTD; + } + else + { + SAL_INFO( + "cppu.typelib", + "type cannot be completed: " << OUString::unacquired(&(*ppTypeDescr)->pTypeName)); + return false; + } + return true; +} + +} + + +extern "C" void typelib_typedescription_newEmpty( + typelib_TypeDescription ** ppRet, + typelib_TypeClass eTypeClass, rtl_uString * pTypeName ) + SAL_THROW_EXTERN_C() +{ + if( *ppRet ) + { + typelib_typedescription_release( *ppRet ); + *ppRet = nullptr; + } + + OSL_ASSERT( typelib_TypeClass_TYPEDEF != eTypeClass ); + + typelib_TypeDescription * pRet; + switch( eTypeClass ) + { + case typelib_TypeClass_SEQUENCE: + { + auto pTmp = allocTypeDescription<typelib_IndirectTypeDescription>(); + pRet = &pTmp->aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nIndirectTypeDescriptionCount ); +#endif + pTmp->pType = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_STRUCT: + { + // FEATURE_EMPTYCLASS + auto pTmp = allocTypeDescription<typelib_StructTypeDescription>(); + pRet = &pTmp->aBase.aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nCompoundTypeDescriptionCount ); +#endif + pTmp->aBase.pBaseTypeDescription = nullptr; + pTmp->aBase.nMembers = 0; + pTmp->aBase.pMemberOffsets = nullptr; + pTmp->aBase.ppTypeRefs = nullptr; + pTmp->aBase.ppMemberNames = nullptr; + pTmp->pParameterizedTypes = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_EXCEPTION: + { + // FEATURE_EMPTYCLASS + auto pTmp = allocTypeDescription<typelib_CompoundTypeDescription>(); + pRet = &pTmp->aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nCompoundTypeDescriptionCount ); +#endif + pTmp->pBaseTypeDescription = nullptr; + pTmp->nMembers = 0; + pTmp->pMemberOffsets = nullptr; + pTmp->ppTypeRefs = nullptr; + pTmp->ppMemberNames = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_ENUM: + { + auto pTmp = allocTypeDescription<typelib_EnumTypeDescription>(); + pRet = &pTmp->aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nEnumTypeDescriptionCount ); +#endif + pTmp->nDefaultEnumValue = 0; + pTmp->nEnumValues = 0; + pTmp->ppEnumNames = nullptr; + pTmp->pEnumValues = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_INTERFACE: + { + auto pTmp = allocTypeDescription< + typelib_InterfaceTypeDescription>(); + pRet = &pTmp->aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nInterfaceTypeDescriptionCount ); +#endif + pTmp->pBaseTypeDescription = nullptr; + pTmp->nMembers = 0; + pTmp->ppMembers = nullptr; + pTmp->nAllMembers = 0; + pTmp->ppAllMembers = nullptr; + pTmp->nMapFunctionIndexToMemberIndex = 0; + pTmp->pMapFunctionIndexToMemberIndex = nullptr; + pTmp->pMapMemberIndexToFunctionIndex= nullptr; + pTmp->nBaseTypes = 0; + pTmp->ppBaseTypes = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + { + auto pTmp = allocTypeDescription< + typelib_InterfaceMethodTypeDescription>(); + pRet = &pTmp->aBase.aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nInterfaceMethodTypeDescriptionCount ); +#endif + pTmp->aBase.pMemberName = nullptr; + pTmp->pReturnTypeRef = nullptr; + pTmp->nParams = 0; + pTmp->pParams = nullptr; + pTmp->nExceptions = 0; + pTmp->ppExceptions = nullptr; + pTmp->pInterface = nullptr; + pTmp->pBaseRef = nullptr; + pTmp->nIndex = 0; + // coverity[leaked_storage] - this is on purpose + } + break; + + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + auto * pTmp = allocTypeDescription< + typelib_InterfaceAttributeTypeDescription>(); + pRet = &pTmp->aBase.aBase; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nInterfaceAttributeTypeDescriptionCount ); +#endif + pTmp->aBase.pMemberName = nullptr; + pTmp->pAttributeTypeRef = nullptr; + pTmp->pInterface = nullptr; + pTmp->pBaseRef = nullptr; + pTmp->nIndex = 0; + pTmp->nGetExceptions = 0; + pTmp->ppGetExceptions = nullptr; + pTmp->nSetExceptions = 0; + pTmp->ppSetExceptions = nullptr; + // coverity[leaked_storage] - this is on purpose + } + break; + + default: + { + pRet = allocTypeDescription<typelib_TypeDescription>(); +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &Init().nTypeDescriptionCount ); +#endif + } + } + + pRet->nRefCount = 1; // reference count is initially 1 + pRet->nStaticRefCount = 0; + pRet->eTypeClass = eTypeClass; + pRet->pUniqueIdentifier = nullptr; + pRet->pReserved = nullptr; + pRet->pTypeName = pTypeName; + rtl_uString_acquire( pRet->pTypeName ); + pRet->pSelf = pRet; + pRet->bComplete = true; + pRet->nSize = 0; + pRet->nAlignment = 0; + pRet->pWeakRef = nullptr; + pRet->bOnDemand = 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 == nullptr || pStructMembers == nullptr) + && (pStructMembers == nullptr || eTypeClass == typelib_TypeClass_STRUCT)); + if (typelib_TypeClass_TYPEDEF == eTypeClass) + { + SAL_WARN("cppu.typelib", "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 ); + reinterpret_cast<typelib_IndirectTypeDescription *>(*ppRet)->pType = pType; + } + break; + + case typelib_TypeClass_EXCEPTION: + case typelib_TypeClass_STRUCT: + { + // FEATURE_EMPTYCLASS + typelib_CompoundTypeDescription * pTmp = reinterpret_cast<typelib_CompoundTypeDescription*>(*ppRet); + + sal_Int32 nOffset = 0; + if( pType ) + { + typelib_typedescriptionreference_getDescription( + reinterpret_cast<typelib_TypeDescription **>(&pTmp->pBaseTypeDescription), pType ); + nOffset = pTmp->pBaseTypeDescription->aBase.nSize; + OSL_ENSURE( newAlignedSize( 0, pTmp->pBaseTypeDescription->aBase.nSize, pTmp->pBaseTypeDescription->aBase.nAlignment ) == pTmp->pBaseTypeDescription->aBase.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 + && OUString::unacquired(&pTypeName).indexOf('<') >= 0; + OSL_ASSERT(!polymorphic || pStructMembers != nullptr); + 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] = nullptr; + if (pCompoundMembers != nullptr) { + typelib_typedescriptionreference_new( + pTmp->ppTypeRefs +i, pCompoundMembers[i].eTypeClass, + pCompoundMembers[i].pTypeName ); + pTmp->ppMemberNames[i] + = pCompoundMembers[i].pMemberName; + rtl_uString_acquire( pTmp->ppMemberNames[i] ); + } else { + typelib_typedescriptionreference_new( + pTmp->ppTypeRefs +i, + pStructMembers[i].aBase.eTypeClass, + pStructMembers[i].aBase.pTypeName ); + pTmp->ppMemberNames[i] + = pStructMembers[i].aBase.pMemberName; + rtl_uString_acquire(pTmp->ppMemberNames[i]); + } + // 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 = nullptr; + 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( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass ) ) + (*ppRet)->pWeakRef = reinterpret_cast<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, nullptr); +} + +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, nullptr, + pMembers); +} + + +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 = reinterpret_cast<typelib_EnumTypeDescription *>(*ppRet); + + pEnum->nDefaultEnumValue = nDefaultValue; + pEnum->nEnumValues = nEnumValues; + pEnum->ppEnumNames = new rtl_uString * [ nEnumValues ]; + for ( sal_Int32 nPos = nEnumValues; nPos--; ) + { + pEnum->ppEnumNames[nPos] = ppEnumNames[nPos]; + rtl_uString_acquire( pEnum->ppEnumNames[nPos] ); + } + pEnum->pEnumValues = new sal_Int32[ nEnumValues ]; + ::memcpy( pEnum->pEnumValues, pEnumValues, nEnumValues * sizeof(sal_Int32) ); + + static_assert(!TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK(typelib_TypeClass_ENUM)); + (*ppRet)->pWeakRef = reinterpret_cast<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_UNUSED_PARAMETER sal_uInt32, SAL_UNUSED_PARAMETER sal_uInt16, + SAL_UNUSED_PARAMETER sal_uInt16, SAL_UNUSED_PARAMETER sal_uInt32, + SAL_UNUSED_PARAMETER sal_uInt32, + typelib_TypeDescriptionReference * pBaseInterface, + sal_Int32 nMembers, + typelib_TypeDescriptionReference ** ppMembers ) + SAL_THROW_EXTERN_C() +{ + // coverity[callee_ptr_arith] - not a bug + typelib_typedescription_newMIInterface( + ppRet, pTypeName, 0, 0, 0, 0, 0, pBaseInterface == nullptr ? 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; + + explicit BaseList(typelib_InterfaceTypeDescription const * desc); + + List const & getList() const { return list; } + + sal_Int32 getBaseMembers() const { return members; } + +private: + typedef std::set< OUString > Set; + + void calculate( + Set& allSet, + sal_Int32 directBaseIndex, Set & directBaseSet, + sal_Int32 * directBaseMembers, + typelib_InterfaceTypeDescription const * desc); + + List list; + sal_Int32 members; +}; + +BaseList::BaseList(typelib_InterfaceTypeDescription const * desc) + : members(0) +{ + Set allSet; + for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) { + Set directBaseSet; + sal_Int32 directBaseMembers = 0; + calculate(allSet, i, directBaseSet, &directBaseMembers, desc->ppBaseTypes[i]); + } +} + +void BaseList::calculate( + Set& allSet, + sal_Int32 directBaseIndex, Set & directBaseSet, + sal_Int32 * directBaseMembers, + typelib_InterfaceTypeDescription const * desc) +{ + for (sal_Int32 i = 0; i < desc->nBaseTypes; ++i) { + calculate(allSet, + directBaseIndex, directBaseSet, directBaseMembers, + desc->ppBaseTypes[i]); + } + if (allSet.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 != nullptr); + members += desc->nMembers; + } + if (directBaseSet.insert(desc->aBase.pTypeName).second) { + OSL_ASSERT(desc->ppAllMembers != nullptr); + *directBaseMembers += desc->nMembers; + } +} + +} + +extern "C" void SAL_CALL typelib_typedescription_newMIInterface( + typelib_InterfaceTypeDescription ** ppRet, + rtl_uString * pTypeName, + SAL_UNUSED_PARAMETER sal_uInt32, SAL_UNUSED_PARAMETER sal_uInt16, + SAL_UNUSED_PARAMETER sal_uInt16, SAL_UNUSED_PARAMETER sal_uInt32, + SAL_UNUSED_PARAMETER sal_uInt32, + sal_Int32 nBaseInterfaces, + typelib_TypeDescriptionReference ** ppBaseInterfaces, + sal_Int32 nMembers, + typelib_TypeDescriptionReference ** ppMembers ) + SAL_THROW_EXTERN_C() +{ + if (*ppRet != nullptr) { + typelib_typedescription_release(&(*ppRet)->aBase); + *ppRet = nullptr; + } + + typelib_InterfaceTypeDescription * pITD = nullptr; + typelib_typedescription_newEmpty( + reinterpret_cast<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] = nullptr; + typelib_typedescriptionreference_getDescription( + reinterpret_cast< typelib_TypeDescription ** >( + &pITD->ppBaseTypes[i]), + ppBaseInterfaces[i]); + if (pITD->ppBaseTypes[i] == nullptr + || !complete( + reinterpret_cast< typelib_TypeDescription ** >( + &pITD->ppBaseTypes[i]), + false)) + { + OSL_ASSERT(false); + return; + } + OSL_ASSERT(pITD->ppBaseTypes[i] != nullptr); + } + if (nBaseInterfaces > 0) { + pITD->pBaseTypeDescription = pITD->ppBaseTypes[0]; + } + // set the + pITD->aUik.m_Data1 = 0; + pITD->aUik.m_Data2 = 0; + pITD->aUik.m_Data3 = 0; + pITD->aUik.m_Data4 = 0; + pITD->aUik.m_Data5 = 0; + + 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 (const auto& rEntry : rList) + { + typelib_InterfaceTypeDescription const * pBase = rEntry.base; + typelib_InterfaceTypeDescription const * pDirectBase + = pITD->ppBaseTypes[rEntry.directBaseIndex]; + OSL_ASSERT(pBase->ppAllMembers != nullptr); + for (sal_Int32 j = 0; j < pBase->nMembers; ++j) { + typelib_TypeDescriptionReference const * pDirectBaseMember + = pDirectBase->ppAllMembers[rEntry.directBaseMemberOffset + j]; + OUString aName = OUString::unacquired(&pDirectBaseMember->pTypeName) + + ":@" + + OUString::number(rEntry.directBaseIndex) + + "," + + OUString::number(rEntry.memberOffset + j) + + ":" + + OUString::unacquired(&pITD->aBase.pTypeName); + typelib_TypeDescriptionReference * pDerivedMember = nullptr; + 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 = &pITD->aBase; + static_assert( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE ) ); + pTmp->pWeakRef = reinterpret_cast<typelib_TypeDescriptionReference *>(pTmp); + pTmp->nSize = typelib_typedescription_getAlignedUnoSize( pTmp, 0, pTmp->nAlignment ); + pTmp->nAlignment = adjustAlignment( pTmp->nAlignment ); + pTmp->bComplete = false; + + *ppRet = pITD; +} + + +namespace { + +typelib_TypeDescriptionReference ** copyExceptions( + sal_Int32 count, rtl_uString ** typeNames) +{ + OSL_ASSERT(count >= 0); + if (count == 0) { + return nullptr; + } + typelib_TypeDescriptionReference ** p + = new typelib_TypeDescriptionReference *[count]; + for (sal_Int32 i = 0; i < count; ++i) { + p[i] = nullptr; + 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 != nullptr) { + typelib_typedescription_release(&(*ppRet)->aBase.aBase); + *ppRet = nullptr; + } + sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength( + pTypeName->buffer, pTypeName->length, ':'); + if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') { + OSL_FAIL("Bad interface method type name"); + return; + } + OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1); + typelib_InterfaceTypeDescription * pInterface = nullptr; + typelib_typedescription_getByName( + reinterpret_cast< typelib_TypeDescription ** >(&pInterface), + aInterfaceTypeName.pData); + if (pInterface == nullptr + || pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE + || !complete( + reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false)) + { + OSL_FAIL("No interface corresponding to interface method"); + return; + } + + typelib_typedescription_newEmpty( + reinterpret_cast<typelib_TypeDescription **>(ppRet), typelib_TypeClass_INTERFACE_METHOD, pTypeName ); + + 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 = pParams[i].pParamName; + rtl_uString_acquire( (*ppRet)->pParams[ i ].pName ); + (*ppRet)->pParams[ i ].pTypeRef = nullptr; + // 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 = nullptr; + OSL_ASSERT( + (nAbsolutePosition >= pInterface->nAllMembers - pInterface->nMembers) + && nAbsolutePosition < pInterface->nAllMembers); + (*ppRet)->nIndex = nAbsolutePosition + - (pInterface->nAllMembers - pInterface->nMembers); + static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_METHOD ) ); + assert(reinterpret_cast<typelib_TypeDescription *>(*ppRet)->pWeakRef == nullptr); +} + + +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, nullptr, 0, nullptr); +} + + +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 != nullptr) { + typelib_typedescription_release(&(*ppRet)->aBase.aBase); + *ppRet = nullptr; + } + sal_Int32 nOffset = rtl_ustr_lastIndexOfChar_WithLength( + pTypeName->buffer, pTypeName->length, ':'); + if (nOffset <= 0 || pTypeName->buffer[nOffset - 1] != ':') { + OSL_FAIL("Bad interface attribute type name"); + return; + } + OUString aInterfaceTypeName(pTypeName->buffer, nOffset - 1); + typelib_InterfaceTypeDescription * pInterface = nullptr; + typelib_typedescription_getByName( + reinterpret_cast< typelib_TypeDescription ** >(&pInterface), + aInterfaceTypeName.pData); + if (pInterface == nullptr + || pInterface->aBase.eTypeClass != typelib_TypeClass_INTERFACE + || !complete( + reinterpret_cast< typelib_TypeDescription ** >(&pInterface), false)) + { + OSL_FAIL("No interface corresponding to interface attribute"); + return; + } + + typelib_typedescription_newEmpty( + reinterpret_cast<typelib_TypeDescription **>(ppRet), typelib_TypeClass_INTERFACE_ATTRIBUTE, pTypeName ); + + 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 = nullptr; + 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); + static_assert( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( typelib_TypeClass_INTERFACE_ATTRIBUTE ) ); + assert(reinterpret_cast<typelib_TypeDescription *>(*ppRet)->pWeakRef == nullptr); +} + + +extern "C" void SAL_CALL typelib_typedescription_acquire( + typelib_TypeDescription * pTypeDescription ) + SAL_THROW_EXTERN_C() +{ + osl_atomic_increment( &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 void typelib_typedescription_destructExtendedMembers( + typelib_TypeDescription * pTD ) +{ + OSL_ASSERT( typelib_TypeClass_TYPEDEF != pTD->eTypeClass ); + + switch( pTD->eTypeClass ) + { + case typelib_TypeClass_SEQUENCE: + if( reinterpret_cast<typelib_IndirectTypeDescription*>(pTD)->pType ) + typelib_typedescriptionreference_release( reinterpret_cast<typelib_IndirectTypeDescription*>(pTD)->pType ); + break; + case typelib_TypeClass_STRUCT: + delete[] reinterpret_cast< typelib_StructTypeDescription * >(pTD)-> + pParameterizedTypes; + [[fallthrough]]; + case typelib_TypeClass_EXCEPTION: + { + typelib_CompoundTypeDescription * pCTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); + if( pCTD->pBaseTypeDescription ) + typelib_typedescription_release( &pCTD->pBaseTypeDescription->aBase ); + 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 = reinterpret_cast<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 = reinterpret_cast<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 != nullptr) { + typelib_typedescriptionreference_release(pIMTD->pBaseRef); + } + } + break; + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_InterfaceAttributeTypeDescription * pIATD = reinterpret_cast<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 != nullptr) { + typelib_typedescriptionreference_release(pIATD->pBaseRef); + } + } + break; + case typelib_TypeClass_ENUM: + { + typelib_EnumTypeDescription * pEnum = reinterpret_cast<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_atomic_decrement( &pTD->nRefCount ); + OSL_ASSERT(ref >= 0); + if (0 != ref) + return; + + TypeDescriptor_Init_Impl &rInit = Init(); + if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTD->eTypeClass ) ) + { + if( pTD->pWeakRef ) + { + { + MutexGuard aGuard( rInit.maMutex ); + // remove this description from the weak reference + pTD->pWeakRef->pType = nullptr; + } + typelib_typedescriptionreference_release( pTD->pWeakRef ); + } + } + else + { + // this description is a reference too, so remove it from the hash table + MutexGuard aGuard( rInit.maMutex ); + WeakMap_Impl::iterator aIt = rInit.maWeakMap.find( pTD->pTypeName->buffer ); + if( aIt != rInit.maWeakMap.end() && static_cast<void *>((*aIt).second) == static_cast<void *>(pTD) ) + { + // remove only if it contains the same object + rInit.maWeakMap.erase( aIt ); + } + } + + typelib_typedescription_destructExtendedMembers( pTD ); + rtl_uString_release( pTD->pTypeName ); + +#if OSL_DEBUG_LEVEL > 0 + switch( pTD->eTypeClass ) + { + case typelib_TypeClass_SEQUENCE: + osl_atomic_decrement( &rInit.nIndirectTypeDescriptionCount ); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + osl_atomic_decrement( &rInit.nCompoundTypeDescriptionCount ); + break; + case typelib_TypeClass_INTERFACE: + osl_atomic_decrement( &rInit.nInterfaceTypeDescriptionCount ); + break; + case typelib_TypeClass_INTERFACE_METHOD: + osl_atomic_decrement( &rInit.nInterfaceMethodTypeDescriptionCount ); + break; + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + osl_atomic_decrement( &rInit.nInterfaceAttributeTypeDescriptionCount ); + break; + case typelib_TypeClass_ENUM: + osl_atomic_decrement( &rInit.nEnumTypeDescriptionCount ); + break; + default: + osl_atomic_decrement( &rInit.nTypeDescriptionCount ); + } +#endif + + freeTypeDescription(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(); + ClearableMutexGuard aGuard( rInit.maMutex ); + + typelib_TypeDescriptionReference * pTDR = nullptr; + typelib_typedescriptionreference_getByName( &pTDR, (*ppNewDescription)->pTypeName ); + + OSL_ASSERT( (*ppNewDescription)->pWeakRef || TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription)->eTypeClass ) ); + if( pTDR ) + { + OSL_ASSERT( (*ppNewDescription)->eTypeClass == pTDR->eTypeClass ); + if( pTDR->pType ) + { + if (TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pTDR->eTypeClass )) + { + // pRef->pType->pWeakRef == 0 means that the description is empty + if (pTDR->pType->pWeakRef) + { + if (osl_atomic_increment( &pTDR->pType->nRefCount ) > 1) + { + // The reference 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; + } + // destruction of this type in progress (another thread!) + (void)osl_atomic_decrement( &pTDR->pType->nRefCount ); + } + // take new descr + pTDR->pType = *ppNewDescription; + OSL_ASSERT( ! (*ppNewDescription)->pWeakRef ); + (*ppNewDescription)->pWeakRef = pTDR; + return; + } + // !reallyWeak + + if ((static_cast<void *>(pTDR) != static_cast<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 && + !reinterpret_cast<typelib_InterfaceTypeDescription *>(pTDR->pType)->ppAllMembers && + (*reinterpret_cast<typelib_InterfaceTypeDescription **>(ppNewDescription))->ppAllMembers))) + { + // uninitialized or incomplete + + if (pTDR->pType->pWeakRef) // if init + { + switch (pTDR->pType->eTypeClass) { + case typelib_TypeClass_ENUM: + { + auto const src = reinterpret_cast<typelib_EnumTypeDescription *>( + *ppNewDescription); + auto const dst = reinterpret_cast<typelib_EnumTypeDescription *>( + pTDR->pType); + assert(dst->nEnumValues == 0); + assert(dst->ppEnumNames == nullptr); + assert(dst->pEnumValues == nullptr); + std::swap(src->nEnumValues, dst->nEnumValues); + std::swap(src->ppEnumNames, dst->ppEnumNames); + std::swap(src->pEnumValues, dst->pEnumValues); + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + auto const src = reinterpret_cast<typelib_CompoundTypeDescription *>( + *ppNewDescription); + auto const dst = reinterpret_cast<typelib_CompoundTypeDescription *>( + pTDR->pType); + assert( + (dst->pBaseTypeDescription == nullptr) + == (src->pBaseTypeDescription == nullptr)); + assert(dst->nMembers == src->nMembers); + assert((dst->pMemberOffsets == nullptr) == (dst->nMembers == 0)); + assert((dst->ppTypeRefs == nullptr) == (dst->nMembers == 0)); + assert(dst->ppMemberNames == nullptr); + assert( + pTDR->pType->eTypeClass != typelib_TypeClass_STRUCT + || ((reinterpret_cast<typelib_StructTypeDescription *>( + dst)->pParameterizedTypes + == nullptr) + == (reinterpret_cast<typelib_StructTypeDescription *>( + src)->pParameterizedTypes + == nullptr))); + std::swap(src->ppMemberNames, dst->ppMemberNames); + break; + } + case typelib_TypeClass_INTERFACE: + { + auto const src = reinterpret_cast<typelib_InterfaceTypeDescription *>( + *ppNewDescription); + auto const dst = reinterpret_cast<typelib_InterfaceTypeDescription *>( + pTDR->pType); + assert( + (dst->pBaseTypeDescription == nullptr) + == (src->pBaseTypeDescription == nullptr)); + assert(dst->nMembers == 0); + assert(dst->ppMembers == nullptr); + assert(dst->nAllMembers == 0); + assert(dst->ppAllMembers == nullptr); + assert(dst->pMapMemberIndexToFunctionIndex == nullptr); + assert(dst->nMapFunctionIndexToMemberIndex == 0); + assert(dst->pMapFunctionIndexToMemberIndex == nullptr); + assert(dst->nBaseTypes == src->nBaseTypes); + assert((dst->ppBaseTypes == nullptr) == (src->ppBaseTypes == nullptr)); + std::swap(src->nMembers, dst->nMembers); + std::swap(src->ppMembers, dst->ppMembers); + std::swap(src->nAllMembers, dst->nAllMembers); + std::swap(src->ppAllMembers, dst->ppAllMembers); + std::swap( + src->pMapMemberIndexToFunctionIndex, + dst->pMapMemberIndexToFunctionIndex); + std::swap( + src->nMapFunctionIndexToMemberIndex, + dst->nMapFunctionIndexToMemberIndex); + std::swap( + src->pMapFunctionIndexToMemberIndex, + dst->pMapFunctionIndexToMemberIndex); + break; + } + default: + assert(false); // this cannot happen + } + } + else + { + // 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 + memcpy( + pTDR->pType +1, + *ppNewDescription +1, + nSize - sizeof(typelib_TypeDescription) ); + + memset( + *ppNewDescription +1, + 0, + nSize - sizeof( typelib_TypeDescription ) ); + } + + pTDR->pType->bComplete = (*ppNewDescription)->bComplete; + pTDR->pType->nSize = (*ppNewDescription)->nSize; + pTDR->pType->nAlignment = (*ppNewDescription)->nAlignment; + + 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 released + assert(pTDR->pType->nRefCount > 1); + // coverity[freed_arg] - pType's nRefCount is > 1 here + 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( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( (*ppNewDescription)->eTypeClass) ) + { + typelib_typedescriptionreference_new( + &pTDR, (*ppNewDescription)->eTypeClass, (*ppNewDescription)->pTypeName ); + } + else + { + pTDR = reinterpret_cast<typelib_TypeDescriptionReference *>(*ppNewDescription); + + // description is the weak itself, so register it + rInit.maWeakMap[pTDR->pTypeName->buffer] = pTDR; + OSL_ASSERT( static_cast<void *>(*ppNewDescription) == static_cast<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 bool type_equals( + typelib_TypeDescriptionReference const * p1, typelib_TypeDescriptionReference const * p2 ) +{ + 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( + reinterpret_cast<typelib_TypeDescriptionReference const *>(p1), reinterpret_cast<typelib_TypeDescriptionReference const *>(p2) ); +} + + +extern "C" sal_Int32 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_ENUM: + nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( typelib_TypeClass )); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + // FEATURE_EMPTYCLASS + { + typelib_CompoundTypeDescription const * pTmp = reinterpret_cast<typelib_CompoundTypeDescription const *>(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 = nullptr; + 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 = std::min(rMaxIntegralTypeSize, sal_Int32( 2 )); + 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_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: +#ifdef AIX + //See previous AIX ifdef comment for an explanation + nSize = (sal_Int32)(sizeof(double)); + rMaxIntegralTypeSize = (sal_Int32)(sizeof(void*)); +#else + nSize = rMaxIntegralTypeSize = sal_Int32(sizeof( double )); +#endif + 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_FAIL( "not convertible 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) { + p[i] = source[i]; + typelib_typedescriptionreference_acquire(p[i]); + } + return p; +} + +bool createDerivedInterfaceMemberDescription( + typelib_TypeDescription ** result, OUString const & name, + typelib_TypeDescriptionReference * baseRef, + typelib_TypeDescription const * base, typelib_TypeDescription * interface, + sal_Int32 index, sal_Int32 position) +{ + if (!baseRef || !base || !interface) + return false; + + 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; + newMethod->aBase.pMemberName + = baseMethod->aBase.pMemberName; + rtl_uString_acquire( + newMethod->aBase.pMemberName); + newMethod->pReturnTypeRef = baseMethod->pReturnTypeRef; + typelib_typedescriptionreference_acquire( + newMethod->pReturnTypeRef); + newMethod->nParams = baseMethod->nParams; + newMethod->pParams = new typelib_MethodParameter[ + newMethod->nParams]; + for (sal_Int32 i = 0; i < newMethod->nParams; ++i) { + newMethod->pParams[i].pName + = baseMethod->pParams[i].pName; + rtl_uString_acquire( + newMethod->pParams[i].pName); + newMethod->pParams[i].pTypeRef + = baseMethod->pParams[i].pTypeRef; + typelib_typedescriptionreference_acquire( + newMethod->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; + newAttribute->aBase.pMemberName + = baseAttribute->aBase.pMemberName; + rtl_uString_acquire(newAttribute->aBase.pMemberName); + newAttribute->bReadOnly = baseAttribute->bReadOnly; + newAttribute->pAttributeTypeRef + = baseAttribute->pAttributeTypeRef; + typelib_typedescriptionreference_acquire(newAttribute->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 = nullptr; + } + + static bool bInited = false; + TypeDescriptor_Init_Impl &rInit = Init(); + + if( !bInited ) + { + // guard against multi thread access + MutexGuard aGuard( rInit.maMutex ); + if( !bInited ) + { + // avoid recursion during the next ...new calls + bInited = true; + + typelib_TypeDescription * pType = nullptr; + typelib_typedescription_new( &pType, typelib_TypeClass_TYPE, OUString("type").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_VOID, OUString("void").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_BOOLEAN, OUString("boolean").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_CHAR, OUString("char").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_BYTE, OUString("byte").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_STRING, OUString("string").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_SHORT, OUString("short").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_SHORT, OUString("unsigned short").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_LONG, OUString("long").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_LONG, OUString("unsigned long").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_HYPER, OUString("hyper").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_UNSIGNED_HYPER, OUString("unsigned hyper").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_FLOAT, OUString("float").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_DOUBLE, OUString("double").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_new( &pType, typelib_TypeClass_ANY, OUString("any").pData, nullptr, 0, nullptr ); + typelib_typedescription_register( &pType ); + typelib_typedescription_release( pType ); + } + } + + typelib_TypeDescriptionReference * pTDR = nullptr; + typelib_typedescriptionreference_getByName( &pTDR, pName ); + if( pTDR ) + { + { + // guard against multi thread access + MutexGuard aGuard( rInit.maMutex ); + // 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 (nullptr != *ppRet) + return; + + // check for sequence + OUString const & name = OUString::unacquired( &pName ); + if (2 < name.getLength() && '[' == name[ 0 ]) + { + OUString element_name( name.copy( 2 ) ); + typelib_TypeDescription * element_td = nullptr; + typelib_typedescription_getByName( &element_td, element_name.pData ); + if (nullptr != element_td) + { + typelib_typedescription_new( + ppRet, typelib_TypeClass_SEQUENCE, pName, element_td->pWeakRef, 0, nullptr ); + // register? + typelib_typedescription_release( element_td ); + } + } + if (nullptr == *ppRet) + { + // Check for derived interface member type: + sal_Int32 i1 = name.lastIndexOf(":@"); + 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 = nullptr; + typelib_TypeDescription * pBase = nullptr; + typelib_TypeDescription * pInterface = nullptr; + typelib_typedescriptionreference_getByName( + &pBaseRef, name.copy(0, i1).pData); + if (pBaseRef != nullptr) { + typelib_typedescriptionreference_getDescription( + &pBase, pBaseRef); + } + typelib_typedescription_getByName( + &pInterface, name.copy(i4 + 1).pData); + if (!createDerivedInterfaceMemberDescription( + ppRet, name, pBaseRef, pBase, pInterface, + o3tl::toInt32(name.subView(i2, i3 - i2)), + o3tl::toInt32(name.subView(i3 + 1, i4 - i3 - 1)))) + { + if (pInterface != nullptr) { + typelib_typedescription_release(pInterface); + } + if (pBase != nullptr) { + typelib_typedescription_release(pBase); + } + if (pBaseRef != nullptr) { + typelib_typedescriptionreference_release( + pBaseRef); + } + } + } + } + } + } + if (nullptr == *ppRet) + { + // on demand access + rInit.callChain( ppRet, pName ); + } + + if( !(*ppRet) ) + return; + + // typedescription found + if (typelib_TypeClass_TYPEDEF == (*ppRet)->eTypeClass) + { + typelib_TypeDescription * pTD = nullptr; + typelib_typedescriptionreference_getDescription( + &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(*ppRet)->pType ); + typelib_typedescription_release( *ppRet ); + *ppRet = pTD; + } + else + { + // set to on demand + (*ppRet)->bOnDemand = true; + // The type description is hold by the reference until + // on demand is activated. + typelib_typedescription_register( ppRet ); + + // insert into the cache + MutexGuard aGuard( rInit.maMutex ); + if( rInit.maCache.size() >= nCacheSize ) + { + typelib_typedescription_release( rInit.maCache.front() ); + rInit.maCache.pop_front(); + } + // descriptions in the cache must be acquired! + typelib_typedescription_acquire( *ppRet ); + rInit.maCache.push_back( *ppRet ); + } +} + +extern "C" void SAL_CALL typelib_typedescriptionreference_newByAsciiName( + typelib_TypeDescriptionReference ** ppTDR, + typelib_TypeClass eTypeClass, + const 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(); + if( eTypeClass == typelib_TypeClass_TYPEDEF ) + { + // on demand access + typelib_TypeDescription * pRet = nullptr; + rInit.callChain( &pRet, pTypeName ); + if( pRet ) + { + // typedescription found + if (typelib_TypeClass_TYPEDEF == pRet->eTypeClass) + { + typelib_typedescriptionreference_acquire( + reinterpret_cast<typelib_IndirectTypeDescription *>(pRet)->pType ); + if (*ppTDR) + typelib_typedescriptionreference_release( *ppTDR ); + *ppTDR = reinterpret_cast<typelib_IndirectTypeDescription *>(pRet)->pType; + typelib_typedescription_release( pRet ); + } + else + { + // set to on demand + pRet->bOnDemand = true; + // The type description is hold by the reference until + // on demand is activated. + typelib_typedescription_register( &pRet ); + + // insert into the cache + MutexGuard aGuard( rInit.maMutex ); + if( rInit.maCache.size() >= nCacheSize ) + { + typelib_typedescription_release( rInit.maCache.front() ); + rInit.maCache.pop_front(); + } + rInit.maCache.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) + { + SAL_INFO("cppu.typelib", "typedef not found : " << pTypeName); + typelib_typedescriptionreference_release( *ppTDR ); + *ppTDR = nullptr; + } + return; + } + + MutexGuard aGuard( rInit.maMutex ); + typelib_typedescriptionreference_getByName( ppTDR, pTypeName ); + if( *ppTDR ) + return; + + if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( eTypeClass ) ) + { + typelib_TypeDescriptionReference * pTDR = new typelib_TypeDescriptionReference; +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_increment( &rInit.nTypeDescriptionReferenceCount ); +#endif + pTDR->nRefCount = 1; + pTDR->nStaticRefCount = 0; + pTDR->eTypeClass = eTypeClass; + pTDR->pUniqueIdentifier = nullptr; + pTDR->pReserved = nullptr; + pTDR->pTypeName = pTypeName; + rtl_uString_acquire( pTDR->pTypeName ); + pTDR->pType = nullptr; + *ppTDR = pTDR; + } + else + { + typelib_typedescription_newEmpty( reinterpret_cast<typelib_TypeDescription ** >(ppTDR), eTypeClass, pTypeName ); + // description will be registered but not acquired + (*reinterpret_cast<typelib_TypeDescription **>(ppTDR))->bOnDemand = true; + (*reinterpret_cast<typelib_TypeDescription **>(ppTDR))->bComplete = false; + } + + // Heavy hack, the const sal_Unicode * is hold by the typedescription reference + // not registered + rInit.maWeakMap[ (*ppTDR)->pTypeName->buffer ] = *ppTDR; +} + + +extern "C" void SAL_CALL typelib_typedescriptionreference_acquire( + typelib_TypeDescriptionReference * pRef ) + SAL_THROW_EXTERN_C() +{ + osl_atomic_increment( &pRef->nRefCount ); +} + + +extern "C" void SAL_CALL typelib_typedescriptionreference_release( + typelib_TypeDescriptionReference * pRef ) + SAL_THROW_EXTERN_C() +{ + // Is it a type description? + if( TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef->eTypeClass ) ) + { + if( ! osl_atomic_decrement( &pRef->nRefCount ) ) + { + TypeDescriptor_Init_Impl &rInit = Init(); + MutexGuard aGuard( rInit.maMutex ); + WeakMap_Impl::iterator aIt = rInit.maWeakMap.find( pRef->pTypeName->buffer ); + if( aIt != rInit.maWeakMap.end() && (*aIt).second == pRef ) + { + // remove only if it contains the same object + rInit.maWeakMap.erase( aIt ); + } + + rtl_uString_release( pRef->pTypeName ); + OSL_ASSERT( pRef->pType == nullptr ); +#if OSL_DEBUG_LEVEL > 0 + osl_atomic_decrement( &rInit.nTypeDescriptionReferenceCount ); +#endif + delete pRef; + } + } + else + { + typelib_typedescription_release( reinterpret_cast<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 = nullptr; + } + + if( !TYPELIB_TYPEDESCRIPTIONREFERENCE_ISREALLYWEAK( pRef->eTypeClass ) && pRef->pType && pRef->pType->pWeakRef ) + { + // reference is a description and initialized + osl_atomic_increment( &reinterpret_cast<typelib_TypeDescription *>(pRef)->nRefCount ); + *ppRet = reinterpret_cast<typelib_TypeDescription *>(pRef); + return; + } + + { + MutexGuard aGuard( Init().maMutex ); + // pRef->pType->pWeakRef == 0 means that the description is empty + if( pRef->pType && pRef->pType->pWeakRef ) + { + sal_Int32 n = osl_atomic_increment( &pRef->pType->nRefCount ); + if( n > 1 ) + { + // The reference is incremented. The object cannot be destroyed. + // Release the guard at the earliest point. + *ppRet = pRef->pType; + return; + } + (void)osl_atomic_decrement( &pRef->pType->nRefCount ); + // destruction of this type in progress (another thread!) + // no access through this weak reference + pRef->pType = nullptr; + } + } + + 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 typelib_typedescriptionreference_getByName( + typelib_TypeDescriptionReference ** ppRet, rtl_uString const * pName ) + SAL_THROW_EXTERN_C() +{ + if( *ppRet ) + { + typelib_typedescriptionreference_release( *ppRet ); + *ppRet = nullptr; + } + TypeDescriptor_Init_Impl &rInit = Init(); + + MutexGuard aGuard( rInit.maMutex ); + WeakMap_Impl::const_iterator aIt = rInit.maWeakMap.find( pName->buffer ); + if( aIt == rInit.maWeakMap.end() ) + return; + + sal_Int32 n = osl_atomic_increment( &(*aIt).second->nRefCount ); + if( n > 1 ) + { + // The reference is incremented. The object cannot be destroyed. + // Release the guard at the earliest point. + *ppRet = (*aIt).second; + } + else + { + // destruction of this type in progress (another thread!) + // no access through this weak reference + (void)osl_atomic_decrement( &(*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 ) + SAL_THROW_EXTERN_C() +{ +} + + +const bool s_aAssignableFromTab[11][11] = +{ + /* from CH, BO, BY, SH, US, LO, UL, HY, UH, FL, DO */ +/* TypeClass_CHAR */ { true, false, false, false, false, false, false, false, false, false, false }, +/* TypeClass_BOOLEAN */ { false, true, false, false, false, false, false, false, false, false, false }, +/* TypeClass_BYTE */ { false, false, true, false, false, false, false, false, false, false, false }, +/* TypeClass_SHORT */ { false, false, true, true, true, false, false, false, false, false, false }, +/* TypeClass_UNSIGNED_SHORT */ { false, false, true, true, true, false, false, false, false, false, false }, +/* TypeClass_LONG */ { false, false, true, true, true, true, true, false, false, false, false }, +/* TypeClass_UNSIGNED_LONG */ { false, false, true, true, true, true, true, false, false, false, false }, +/* TypeClass_HYPER */ { false, false, true, true, true, true, true, true, true, false, false }, +/* TypeClass_UNSIGNED_HYPER */ { false, false, true, true, true, true, true, true, true, false, false }, +/* TypeClass_FLOAT */ { false, false, true, true, true, false, false, false, false, true, false }, +/* TypeClass_DOUBLE */ { false, false, true, true, true, true, true, false, false, true, true } +}; + + +extern "C" sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom( + typelib_TypeDescriptionReference * pAssignable, + typelib_TypeDescriptionReference * pFrom ) + SAL_THROW_EXTERN_C() +{ + if (!pAssignable || !pFrom) + return false; + + typelib_TypeClass eAssignable = pAssignable->eTypeClass; + typelib_TypeClass eFrom = pFrom->eTypeClass; + + if (eAssignable == typelib_TypeClass_ANY) // anything can be assigned to an any .) + return true; + if (eAssignable == eFrom) + { + if (type_equals( pAssignable, pFrom )) // first shot + { + return true; + } + switch (eAssignable) + { + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pFromDescr = nullptr; + TYPELIB_DANGER_GET( &pFromDescr, pFrom ); + if (!reinterpret_cast<typelib_CompoundTypeDescription *>(pFromDescr)->pBaseTypeDescription) + { + TYPELIB_DANGER_RELEASE( pFromDescr ); + return false; + } + bool bRet = typelib_typedescriptionreference_isAssignableFrom( + pAssignable, + reinterpret_cast<typelib_CompoundTypeDescription *>(pFromDescr)->pBaseTypeDescription->aBase.pWeakRef ); + TYPELIB_DANGER_RELEASE( pFromDescr ); + return bRet; + } + case typelib_TypeClass_INTERFACE: + { + typelib_TypeDescription * pFromDescr = nullptr; + 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 false; + } + } + } + return (eAssignable >= typelib_TypeClass_CHAR && eAssignable <= typelib_TypeClass_DOUBLE && + eFrom >= typelib_TypeClass_CHAR && eFrom <= typelib_TypeClass_DOUBLE && + s_aAssignableFromTab[eAssignable-1][eFrom-1]); +} + +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); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cppu/source/typelib/typelib.hxx b/cppu/source/typelib/typelib.hxx new file mode 100644 index 000000000..b62e763de --- /dev/null +++ b/cppu/source/typelib/typelib.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#pragma once + +#include <rtl/ustring.h> +#include <sal/types.h> +#include <typelib/typeclass.h> +#include <typelib/typedescription.h> + +extern "C" sal_Int32 typelib_typedescription_getAlignedUnoSize( + const typelib_TypeDescription * pTypeDescription, + sal_Int32 nOffset, + sal_Int32 & rMaxIntegralTypeSize ) + SAL_THROW_EXTERN_C(); + + +extern "C" void typelib_typedescription_newEmpty( + typelib_TypeDescription ** ppRet, + typelib_TypeClass eTypeClass, + rtl_uString * pTypeName ) + SAL_THROW_EXTERN_C(); + +extern "C" void typelib_typedescriptionreference_getByName( + typelib_TypeDescriptionReference ** ppRet, + rtl_uString const * pName ) + SAL_THROW_EXTERN_C(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |