diff options
Diffstat (limited to 'cppu/source/uno')
-rw-r--r-- | cppu/source/uno/EnvDcp.c | 49 | ||||
-rw-r--r-- | cppu/source/uno/EnvStack.cxx | 380 | ||||
-rw-r--r-- | cppu/source/uno/IdentityMapping.cxx | 106 | ||||
-rw-r--r-- | cppu/source/uno/IdentityMapping.hxx | 39 | ||||
-rw-r--r-- | cppu/source/uno/any.cxx | 150 | ||||
-rw-r--r-- | cppu/source/uno/assign.hxx | 635 | ||||
-rw-r--r-- | cppu/source/uno/cascade_mapping.cxx | 341 | ||||
-rw-r--r-- | cppu/source/uno/cascade_mapping.hxx | 41 | ||||
-rw-r--r-- | cppu/source/uno/constr.hxx | 267 | ||||
-rw-r--r-- | cppu/source/uno/copy.hxx | 886 | ||||
-rw-r--r-- | cppu/source/uno/data.cxx | 617 | ||||
-rw-r--r-- | cppu/source/uno/destr.hxx | 438 | ||||
-rw-r--r-- | cppu/source/uno/env_subst.cxx | 54 | ||||
-rw-r--r-- | cppu/source/uno/env_subst.hxx | 41 | ||||
-rw-r--r-- | cppu/source/uno/eq.hxx | 668 | ||||
-rw-r--r-- | cppu/source/uno/lbenv.cxx | 1182 | ||||
-rw-r--r-- | cppu/source/uno/lbmap.cxx | 692 | ||||
-rw-r--r-- | cppu/source/uno/loadmodule.cxx | 55 | ||||
-rw-r--r-- | cppu/source/uno/loadmodule.hxx | 51 | ||||
-rw-r--r-- | cppu/source/uno/makefile.mk | 55 | ||||
-rw-r--r-- | cppu/source/uno/prim.hxx | 206 | ||||
-rw-r--r-- | cppu/source/uno/sequence.cxx | 1016 |
22 files changed, 7969 insertions, 0 deletions
diff --git a/cppu/source/uno/EnvDcp.c b/cppu/source/uno/EnvDcp.c new file mode 100644 index 000000000000..7fb9a0e0ee68 --- /dev/null +++ b/cppu/source/uno/EnvDcp.c @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/EnvDcp.h" + + +void uno_EnvDcp_getTypeName(rtl_uString const * pEnvDcp, rtl_uString ** ppEnvTypeName) +{ + sal_Int32 colIdx = rtl_ustr_indexOfChar_WithLength(pEnvDcp->buffer, pEnvDcp->length, ':'); + if (colIdx >= 0) + rtl_uString_newFromStr_WithLength(ppEnvTypeName, pEnvDcp->buffer, colIdx); + + else + rtl_uString_newFromStr(ppEnvTypeName, pEnvDcp->buffer); +} + +void uno_EnvDcp_getPurpose(rtl_uString const * pEnvDcp, rtl_uString ** ppEnvPurpose) +{ + sal_Int32 colIdx = rtl_ustr_indexOfChar_WithLength(pEnvDcp->buffer, pEnvDcp->length, ':'); + if (colIdx >= 0) + rtl_uString_newFromStr_WithLength(ppEnvPurpose, pEnvDcp->buffer + colIdx, pEnvDcp->length - colIdx); + + else + rtl_uString_new(ppEnvPurpose); +} diff --git a/cppu/source/uno/EnvStack.cxx b/cppu/source/uno/EnvStack.cxx new file mode 100644 index 000000000000..b7cefd42b4da --- /dev/null +++ b/cppu/source/uno/EnvStack.cxx @@ -0,0 +1,380 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "uno/environment.hxx" + +#include "cppu/EnvDcp.hxx" +#include "cppu/Enterable.hxx" + +#include "osl/thread.h" +#include "osl/mutex.hxx" + +#include <hash_map> + + +using namespace com::sun::star; + + +struct SAL_DLLPRIVATE oslThreadIdentifier_equal +{ + bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const; +}; + +bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const +{ + bool result = s1 == s2; + + return result; +} + + +struct SAL_DLLPRIVATE oslThreadIdentifier_hash +{ + size_t operator()(oslThreadIdentifier s1) const; +}; + +size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const +{ + return s1; +} + +typedef ::std::hash_map<oslThreadIdentifier, + uno_Environment *, + oslThreadIdentifier_hash, + oslThreadIdentifier_equal> ThreadMap; + +static osl::Mutex s_threadMap_mutex; +static ThreadMap s_threadMap; + + +static rtl::OUString s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)); + +static void s_setCurrent(uno_Environment * pEnv) +{ + oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL); + + osl::MutexGuard guard(s_threadMap_mutex); + if (pEnv) + s_threadMap[threadId] = pEnv; + + else + { + ThreadMap::iterator iEnv = s_threadMap.find(threadId); + s_threadMap.erase(iEnv); + } +} + +static uno_Environment * s_getCurrent(void) +{ + uno_Environment * pEnv = NULL; + + oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL); + + osl::MutexGuard guard(s_threadMap_mutex); + ThreadMap::iterator iEnv = s_threadMap.find(threadId); + if(iEnv != s_threadMap.end()) + pEnv = iEnv->second; + + return pEnv; +} + + +extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName) + SAL_THROW_EXTERN_C() +{ + if (*ppEnv) + { + (*ppEnv)->release(*ppEnv); + *ppEnv = NULL; + } + + rtl::OUString currPurpose; + + uno_Environment * pCurrEnv = s_getCurrent(); + if (pCurrEnv) // no environment means no purpose + currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName); + + if (pTypeName && rtl_uString_getLength(pTypeName)) + { + rtl::OUString envDcp(pTypeName); + envDcp += currPurpose; + + uno_getEnvironment(ppEnv, envDcp.pData, NULL); + } + else + { + if (pCurrEnv) + { + *ppEnv = pCurrEnv; + (*ppEnv)->acquire(*ppEnv); + } + else + uno_getEnvironment(ppEnv, s_uno_envDcp.pData, NULL); + + } +} + +static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) +{ + sal_Int32 nIndex1 = 0; + sal_Int32 nIndex2 = 0; + sal_Int32 sim = 0; + + rtl::OUString token1; + rtl::OUString token2; + + do + { + token1 = str1.getToken(0, ':', nIndex1); + token2 = str2.getToken(0, ':', nIndex2); + + if (token1.equals(token2)) + sim += token1.getLength() + 1; + } + while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); + + rtl::OUString result; + + if (sim) + result = str1.copy(0, sim - 1); + + return result; +} + +static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv) +{ + int res = 0; + + rtl::OUString nextPurpose; + + rtl::OUString currPurpose; + if (pCurrEnv) + currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName); + + rtl::OUString targetPurpose; + if (pTargetEnv) + targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName); + + rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose)); + if (currPurpose.getLength() > intermPurpose.getLength()) + { + sal_Int32 idx = currPurpose.lastIndexOf(':'); + nextPurpose = currPurpose.copy(0, idx); + + res = -1; + } + else if (intermPurpose.getLength() < targetPurpose.getLength()) + { + sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1); + if (idx == -1) + nextPurpose = targetPurpose; + + else + nextPurpose = targetPurpose.copy(0, idx); + + res = 1; + } + + if (nextPurpose.getLength()) + { + rtl::OUString next_envDcp(s_uno_envDcp); + next_envDcp += nextPurpose; + + uno_getEnvironment(ppEnv, next_envDcp.pData, NULL); + } + else + { + if (*ppEnv) + (*ppEnv)->release(*ppEnv); + + *ppEnv = NULL; + } + + return res; +} + +extern "C" { static void s_pull(va_list * pParam) +{ + uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *); + va_list * pXparam = va_arg(*pParam, va_list *); + + pCallee(pXparam); +}} + +static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam) +{ + cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); + if (pEnterable) + pEnterable->callInto(s_pull, pCallee, pParam); + + else + pCallee(pParam); +} + +static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) +{ + va_list param; + + va_start(param, pCallee); + s_callInto_v(pEnv, pCallee, ¶m); + va_end(param); +} + +static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam) +{ + cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); + if (pEnterable) + pEnterable->callOut_v(pCallee, pParam); + + else + pCallee(pParam); +} + +static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) +{ + va_list param; + + va_start(param, pCallee); + s_callOut_v(pEnv, pCallee, ¶m); + va_end(param); +} + +static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *); + +extern "C" { static void s_environment_invoke_vv(va_list * pParam) +{ + uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *); + uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *); + uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *); + va_list * pXparam = va_arg(*pParam, va_list *); + + s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam); +}} + +static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam) +{ + uno_Environment * pNextEnv = NULL; + switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) + { + case -1: + s_setCurrent(pNextEnv); + s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam); + s_setCurrent(pCurrEnv); + break; + + case 0: { + uno_Environment * hld = s_getCurrent(); + s_setCurrent(pCurrEnv); + pCallee(pParam); + s_setCurrent(hld); + } + break; + + case 1: + s_setCurrent(pNextEnv); + s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam); + s_setCurrent(pCurrEnv); + break; + } + + if (pNextEnv) + pNextEnv->release(pNextEnv); +} + +extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam) + SAL_THROW_EXTERN_C() +{ + s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam); +} + +extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) + SAL_THROW_EXTERN_C() +{ + va_list param; + + va_start(param, pCallee); + uno_Environment_invoke_v(pEnv, pCallee, ¶m); + va_end(param); +} + +extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv) + SAL_THROW_EXTERN_C() +{ + uno_Environment * pNextEnv = NULL; + uno_Environment * pCurrEnv = s_getCurrent(); + + int res; + while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0) + { + cppu::Enterable * pEnterable; + + switch(res) + { + case -1: + pEnterable = reinterpret_cast<cppu::Enterable *>(pCurrEnv->pReserved); + if (pEnterable) + pEnterable->leave(); + pCurrEnv->release(pCurrEnv); + break; + + case 1: + pNextEnv->acquire(pNextEnv); + pEnterable = reinterpret_cast<cppu::Enterable *>(pNextEnv->pReserved); + if (pEnterable) + pEnterable->enter(); + break; + } + + s_setCurrent(pNextEnv); + pCurrEnv = pNextEnv; + } +} + +int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason) + SAL_THROW_EXTERN_C() +{ + int result = 1; + + rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName)); + if (typeName.equals(s_uno_envDcp)) + { + cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved); + if (pEnterable) + result = pEnterable->isValid((rtl::OUString *)pReason); + } + else + { + rtl::OUString envDcp(s_uno_envDcp); + envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName); + + uno::Environment env(envDcp); + + result = env.isValid((rtl::OUString *)pReason); + } + + return result; +} diff --git a/cppu/source/uno/IdentityMapping.cxx b/cppu/source/uno/IdentityMapping.cxx new file mode 100644 index 000000000000..64721e2993ca --- /dev/null +++ b/cppu/source/uno/IdentityMapping.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "IdentityMapping.hxx" + +#include "uno/mapping.h" +#include "uno/environment.hxx" + +#include "osl/interlck.h" + + +using namespace ::com::sun::star; + +struct IdentityMapping : public uno_Mapping +{ + sal_Int32 m_nRef; + uno::Environment m_env; + + IdentityMapping(uno::Environment const & rEnv); +}; + +extern "C" +{ + +static void SAL_CALL s_free(uno_Mapping * pMapping) SAL_THROW(()) +{ + delete static_cast<IdentityMapping *>(pMapping); +} + +static void SAL_CALL s_acquire(uno_Mapping * pMapping) SAL_THROW(()) +{ + static rtl::OUString s_purpose; + + if (1 == ::osl_incrementInterlockedCount(&static_cast<IdentityMapping *>(pMapping)->m_nRef)) + { + uno_registerMapping( + &pMapping, + s_free, + static_cast<IdentityMapping *>(pMapping)->m_env.get(), + static_cast<IdentityMapping *>(pMapping)->m_env.get(), + s_purpose.pData); + } +} + +static void SAL_CALL s_release(uno_Mapping * pMapping) SAL_THROW(()) +{ + if (!::osl_decrementInterlockedCount(&static_cast<IdentityMapping *>(pMapping )->m_nRef)) + uno_revokeMapping(pMapping); +} + +static void SAL_CALL s_mapInterface(uno_Mapping * pMapping, + void ** ppOut, + void * pInterface, + struct _typelib_InterfaceTypeDescription * /*pInterfaceTypeDescr*/) + SAL_THROW(()) +{ + *ppOut = pInterface; + + if (pInterface) + { + IdentityMapping * that = static_cast<IdentityMapping *>(pMapping); + + (that->m_env.get()->pExtEnv->acquireInterface)(that->m_env.get()->pExtEnv, pInterface); + } +} +} + + +IdentityMapping::IdentityMapping(uno::Environment const & rEnv) + : m_nRef(0), + m_env(rEnv) +{ + uno_Mapping::acquire = s_acquire; + uno_Mapping::release = s_release; + uno_Mapping::mapInterface = s_mapInterface; +} + + +uno_Mapping * createIdentityMapping(uno::Environment const & rEnv) SAL_THROW(()) +{ + return new IdentityMapping(rEnv); +} diff --git a/cppu/source/uno/IdentityMapping.hxx b/cppu/source/uno/IdentityMapping.hxx new file mode 100644 index 000000000000..cf95a30b203c --- /dev/null +++ b/cppu/source/uno/IdentityMapping.hxx @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_IdentityMapping_hxx +#define INCLUDED_IdentityMapping_hxx + +#include "uno/mapping.h" + +namespace com { namespace sun { namespace star { namespace uno { +class Environment; +}}}} + +uno_Mapping * createIdentityMapping(const ::com::sun::star::uno::Environment & rEnv); + +#endif diff --git a/cppu/source/uno/any.cxx b/cppu/source/uno/any.cxx new file mode 100644 index 000000000000..29be833dfb86 --- /dev/null +++ b/cppu/source/uno/any.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" + +#include "copy.hxx" +#include "destr.hxx" + +using namespace cppu; + + +extern "C" +{ +//################################################################################################## +void SAL_CALL uno_type_any_assign( + uno_Any * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructAny( pDest, release ); + if (pType) + { + _copyConstructAny( pDest, pSource, pType, 0, acquire, 0 ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_any_assign( + uno_Any * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructAny( pDest, release ); + if (pTypeDescr) + { + _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, 0 ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_type_any_construct( + uno_Any * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + if (pType) + { + _copyConstructAny( pDest, pSource, pType, 0, acquire, 0 ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_any_construct( + uno_Any * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + if (pTypeDescr) + { + _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, 0 ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_type_any_constructAndConvert( + uno_Any * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, + uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + if (pType) + { + _copyConstructAny( pDest, pSource, pType, 0, 0, mapping ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_any_constructAndConvert( + uno_Any * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + if (pTypeDescr) + { + _copyConstructAny( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, 0, mapping ); + } + else + { + CONSTRUCT_EMPTY_ANY( pDest ); + } +} +//################################################################################################## +void SAL_CALL uno_any_destruct( uno_Any * pValue, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructAny( pValue, release ); +} +//################################################################################################## +void SAL_CALL uno_any_clear( uno_Any * pValue, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructAny( pValue, release ); + CONSTRUCT_EMPTY_ANY( pValue ); +} +} diff --git a/cppu/source/uno/assign.hxx b/cppu/source/uno/assign.hxx new file mode 100644 index 000000000000..256bb31565db --- /dev/null +++ b/cppu/source/uno/assign.hxx @@ -0,0 +1,635 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef ASSIGN_HXX +#define ASSIGN_HXX + +#include "prim.hxx" +#include "destr.hxx" +#include "constr.hxx" +#include "copy.hxx" + + +namespace cppu +{ + +//################################################################################################## +//#### assignment ################################################################################## +//################################################################################################## + + +//-------------------------------------------------------------------------------------------------- +inline void _assignInterface( + void ** ppDest, void * pSource, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + _acquire( pSource, acquire ); + void * const pToBeReleased = *ppDest; + *ppDest = pSource; + _release( pToBeReleased, release ); +} +//-------------------------------------------------------------------------------------------------- +inline void * _queryInterface( + void * pSource, + typelib_TypeDescriptionReference * pDestType, + uno_QueryInterfaceFunc queryInterface ) + SAL_THROW( () ) +{ + if (pSource) + { + if (0 == queryInterface) + queryInterface = binuno_queryInterface; + pSource = (*queryInterface)( pSource, pDestType ); + } + return pSource; +} +//================================================================================================== +sal_Bool assignStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _assignStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pTypeDescr->pBaseTypeDescription) + { + // copy base value + if (! assignStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, + queryInterface, acquire, release )) + { + return sal_False; + } + } + // then copy members + typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + while (nDescr--) + { + if (! ::uno_type_assignData( (char *)pDest + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], + (char *)pSource + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], + queryInterface, acquire, release )) + { + return sal_False; + } + } + return sal_True; +} +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _assignArray( + void * pDest, void * pSource, + typelib_ArrayTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) +{ + typelib_TypeDescriptionReference * pElementTypeRef = + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; + typelib_TypeDescription * pElementTypeDescr = NULL; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementTypeRef ); + sal_Int32 nTotalElements = pTypeDescr->nTotalElements; + sal_Int32 nElementSize = pElementTypeDescr->nSize; + sal_Int32 i; + sal_Bool bRet = sal_False; + + switch ( pElementTypeRef->eTypeClass ) + { + case typelib_TypeClass_CHAR: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + for (i=0; i < nTotalElements; i++) + { + ::rtl_copyMemory((sal_Char *)pDest + i * nElementSize, + (sal_Char *)pSource + i * nElementSize, + nElementSize); + } + bRet = sal_True; + break; + case typelib_TypeClass_STRING: + for (i=0; i < nTotalElements; i++) + { + ::rtl_uString_assign( (rtl_uString **)pDest + i, + ((rtl_uString **)pSource)[i] ); + } + bRet = sal_True; + break; + case typelib_TypeClass_TYPE: + for (i=0; i < nTotalElements; i++) + { + typelib_TypeDescriptionReference ** pp = (typelib_TypeDescriptionReference **)pDest + i; + ::typelib_typedescriptionreference_release( *pp ); + *pp = *((typelib_TypeDescriptionReference **)pSource + i); + TYPE_ACQUIRE( *pp ); + } + bRet = sal_True; + break; + case typelib_TypeClass_ANY: + for (i=0; i < nTotalElements; i++) + { + _destructAny( (uno_Any *)pDest + i, release ); + _copyConstructAny( (uno_Any *)pDest + i, (uno_Any *)pSource + i, + pElementTypeRef, pElementTypeDescr, acquire, 0 ); + } + bRet = sal_True; + break; + case typelib_TypeClass_ENUM: + for (i=0; i < nTotalElements; i++) + { + *((sal_Int32 *)pDest + i) = *((sal_Int32 *)pSource + i); + } + bRet = sal_True; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + for (i=0; i < nTotalElements; i++) + { + bRet = _assignStruct( (sal_Char *)pDest + i * nElementSize, + (sal_Char *)pSource + i * nElementSize, + (typelib_CompoundTypeDescription *)pElementTypeDescr, + queryInterface, acquire, release ); + if (! bRet) + break; + } + bRet = sal_True; + break; + case typelib_TypeClass_UNION: + for (i=0; i < nTotalElements; i++) + { + _destructUnion( (sal_Char*)pDest + i * nElementSize, pElementTypeDescr, release ); + _copyConstructUnion( (sal_Char*)pDest + i * nElementSize, + (sal_Char*)pSource + i * nElementSize, + pElementTypeDescr, acquire, 0 ); + } + bRet = sal_True; + break; + case typelib_TypeClass_SEQUENCE: + for (i=0; i < nTotalElements; i++) + { + ::osl_incrementInterlockedCount( + &(*((uno_Sequence **)pSource + i))->nRefCount ); + idestructSequence( + *((uno_Sequence **)pDest + i), + pElementTypeRef, pElementTypeDescr, release ); + *((uno_Sequence **)pDest + i) = *((uno_Sequence **)pSource + i); + } + bRet = sal_True; + break; + case typelib_TypeClass_INTERFACE: + for (i=0; i < nTotalElements; i++) + { + _assignInterface( + (void **)((sal_Char*)pDest + i * nElementSize), + *(void **)((sal_Char*)pSource + i * nElementSize), + acquire, release ); + } + bRet = sal_True; + break; + default: + OSL_ASSERT(false); + break; + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return bRet; +} +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _assignData( + void * pDest, + typelib_TypeDescriptionReference * pDestType, typelib_TypeDescription * pDestTypeDescr, + void * pSource, + typelib_TypeDescriptionReference * pSourceType, typelib_TypeDescription * pSourceTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pDest == pSource) + return _type_equals( pDestType, pSourceType ); + + if (! pSource) + { + _destructData( pDest, pDestType, pDestTypeDescr, release ); + _defaultConstructData( pDest, pDestType, pDestTypeDescr ); + return sal_True; + } + while (typelib_TypeClass_ANY == pSourceType->eTypeClass) + { + pSourceTypeDescr = 0; + pSourceType = ((uno_Any *)pSource)->pType; + pSource = ((uno_Any *)pSource)->pData; + if (pDest == pSource) + return sal_True; + } + + switch (pDestType->eTypeClass) + { + case typelib_TypeClass_VOID: + return pSourceType->eTypeClass == typelib_TypeClass_VOID; + case typelib_TypeClass_CHAR: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_CHAR: + *(sal_Unicode *)pDest = *(sal_Unicode *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_BOOLEAN: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + *(sal_Bool *)pDest = (*(sal_Bool *)pSource != sal_False); + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_BYTE: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_Int8 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_SHORT: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_Int16 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int16 *)pDest = *(sal_Int16 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_SHORT: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_uInt16 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_uInt16 *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_LONG: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_Int32 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(sal_Int32 *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int32 *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_Int32 *)pDest = *(sal_Int32 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_LONG: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_uInt32 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(sal_uInt32 *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_uInt32 *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_uInt32 *)pDest = *(sal_uInt32 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_HYPER: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_Int64 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(sal_Int64 *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int64 *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_LONG: + *(sal_Int64 *)pDest = *(sal_Int32 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_Int64 *)pDest = *(sal_uInt32 *)pSource; + return sal_True; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_Int64 *)pDest = *(sal_Int64 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_HYPER: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(sal_uInt64 *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(sal_uInt64 *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_uInt64 *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_LONG: + *(sal_uInt64 *)pDest = *(sal_Int32 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_uInt64 *)pDest = *(sal_uInt32 *)pSource; + return sal_True; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_uInt64 *)pDest = *(sal_uInt64 *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_FLOAT: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(float *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(float *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(float *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_FLOAT: + *(float *)pDest = *(float *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_DOUBLE: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_BYTE: + *(double *)pDest = *(sal_Int8 *)pSource; + return sal_True; + case typelib_TypeClass_SHORT: + *(double *)pDest = *(sal_Int16 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_SHORT: + *(double *)pDest = *(sal_uInt16 *)pSource; + return sal_True; + case typelib_TypeClass_LONG: + *(double *)pDest = *(sal_Int32 *)pSource; + return sal_True; + case typelib_TypeClass_UNSIGNED_LONG: + *(double *)pDest = *(sal_uInt32 *)pSource; + return sal_True; + case typelib_TypeClass_FLOAT: + *(double *)pDest = *(float *)pSource; + return sal_True; + case typelib_TypeClass_DOUBLE: + *(double *)pDest = *(double *)pSource; + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_STRING: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_STRING: + ::rtl_uString_assign( (rtl_uString **)pDest, *(rtl_uString **)pSource ); + return sal_True; + default: + return sal_False; + } + case typelib_TypeClass_TYPE: + switch (pSourceType->eTypeClass) + { + case typelib_TypeClass_TYPE: + { + typelib_TypeDescriptionReference ** pp = (typelib_TypeDescriptionReference **)pDest; + ::typelib_typedescriptionreference_release( *pp ); + *pp = *(typelib_TypeDescriptionReference **)pSource; + TYPE_ACQUIRE( *pp ); + return sal_True; + } + default: + return sal_False; + } + case typelib_TypeClass_ANY: + _destructAny( (uno_Any *)pDest, release ); + _copyConstructAny( (uno_Any *)pDest, pSource, pSourceType, pSourceTypeDescr, acquire, 0 ); + return sal_True; + case typelib_TypeClass_ENUM: + if (_type_equals( pDestType, pSourceType )) + { + *(sal_Int32 *)pDest = *(sal_Int32 *)pSource; + return sal_True; + } + return sal_False; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (typelib_TypeClass_STRUCT == pSourceType->eTypeClass || + typelib_TypeClass_EXCEPTION == pSourceType->eTypeClass) + { + sal_Bool bRet = sal_False; + if (pSourceTypeDescr) + { + typelib_CompoundTypeDescription * pTypeDescr = + (typelib_CompoundTypeDescription *)pSourceTypeDescr; + while (pTypeDescr && + !_type_equals( + ((typelib_TypeDescription *)pTypeDescr)->pWeakRef, pDestType )) + { + pTypeDescr = pTypeDescr->pBaseTypeDescription; + } + if (pTypeDescr) + { + bRet = _assignStruct( + pDest, pSource, pTypeDescr, queryInterface, acquire, release ); + } + } + else + { + TYPELIB_DANGER_GET( &pSourceTypeDescr, pSourceType ); + typelib_CompoundTypeDescription * pTypeDescr = + (typelib_CompoundTypeDescription *)pSourceTypeDescr; + while (pTypeDescr && + !_type_equals( + ((typelib_TypeDescription *)pTypeDescr)->pWeakRef, pDestType )) + { + pTypeDescr = pTypeDescr->pBaseTypeDescription; + } + if (pTypeDescr) + { + bRet = _assignStruct( + pDest, pSource, pTypeDescr, queryInterface, acquire, release ); + } + TYPELIB_DANGER_RELEASE( pSourceTypeDescr ); + } + return bRet; + } + return sal_False; + case typelib_TypeClass_ARRAY: + { + sal_Bool bRet = sal_False; + if (pSourceTypeDescr) + { + typelib_ArrayTypeDescription * pTypeDescr = + (typelib_ArrayTypeDescription *)pSourceTypeDescr; + bRet = _assignArray( pDest, pSource, pTypeDescr, queryInterface, acquire, release ); + } + else + { + TYPELIB_DANGER_GET( &pSourceTypeDescr, pSourceType ); + typelib_ArrayTypeDescription * pTypeDescr = + (typelib_ArrayTypeDescription *)pSourceTypeDescr; + if ( pTypeDescr ) + { + bRet = _assignArray( + pDest, pSource, pTypeDescr, queryInterface, acquire, release ); + } + TYPELIB_DANGER_RELEASE( pSourceTypeDescr ); + } + return bRet; + } + case typelib_TypeClass_UNION: + if (_type_equals( pDestType, pSourceType )) + { + if (pDestTypeDescr) + { + _destructUnion( pDest, pDestTypeDescr, release ); + _copyConstructUnion( pDest, pSource, pDestTypeDescr, acquire, 0 ); + } + else + { + TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType ); + _destructUnion( pDest, pDestTypeDescr, release ); + _copyConstructUnion( pDest, pSource, pDestTypeDescr, acquire, 0 ); + TYPELIB_DANGER_RELEASE( pDestTypeDescr ); + } + return sal_True; + } + return sal_False; + case typelib_TypeClass_SEQUENCE: + if (typelib_TypeClass_SEQUENCE != pSourceType->eTypeClass) + return sal_False; + // self assignment: + if (*(uno_Sequence **)pSource == *(uno_Sequence **)pDest) + return sal_True; + if (_type_equals( pDestType, pSourceType )) + { + ::osl_incrementInterlockedCount( + &(*(uno_Sequence **)pSource)->nRefCount ); + idestructSequence( + *(uno_Sequence **)pDest, pDestType, pDestTypeDescr, release ); + *(uno_Sequence **)pDest = *(uno_Sequence **)pSource; + return sal_True; + } + return sal_False; + case typelib_TypeClass_INTERFACE: + if (typelib_TypeClass_INTERFACE != pSourceType->eTypeClass) + return sal_False; + if (_type_equals( pDestType, pSourceType )) + { + _assignInterface( (void **)pDest, *(void **)pSource, acquire, release ); + return sal_True; + } + else if (*static_cast< void ** >(pSource) == 0) + { + // A null reference of any interface type can be converted to a null + // reference of any other interface type: + void * const pToBeReleased = *static_cast< void ** >(pDest); + *static_cast< void ** >(pDest) = 0; + _release( pToBeReleased, release ); + return true; + } + else + { + if (pSourceTypeDescr) + { + typelib_TypeDescription * pTD = pSourceTypeDescr; + while (pTD && !_type_equals( pTD->pWeakRef, pDestType )) + { + pTD = (typelib_TypeDescription *) + ((typelib_InterfaceTypeDescription *)pTD)->pBaseTypeDescription; + } + if (pTD) // is base of dest + { + _assignInterface( (void **)pDest, *(void **)pSource, acquire, release ); + return true; + } + } + + // query for interface: + void * pQueried = _queryInterface( *static_cast<void **>(pSource), + pDestType, queryInterface ); + if (pQueried != 0) { + void * const pToBeReleased = *static_cast<void **>(pDest); + *static_cast<void **>(pDest) = pQueried; + _release( pToBeReleased, release ); + } + return (pQueried != 0); + } + default: + OSL_ASSERT(false); + return sal_False; + } +} + +} + +#endif diff --git a/cppu/source/uno/cascade_mapping.cxx b/cppu/source/uno/cascade_mapping.cxx new file mode 100644 index 000000000000..ee870a52e286 --- /dev/null +++ b/cppu/source/uno/cascade_mapping.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <iostream> + +#include "osl/interlck.h" +#include "rtl/ustring.hxx" +#include "uno/environment.hxx" +#include "uno/mapping.hxx" +#include "uno/dispatcher.h" + +//#include "cascade_mappping.hxx" +#include "cppu/EnvDcp.hxx" + + +//#define LOG_CALLING_named_purpose_getMapping + +//#define LOG_LIFECYLE_MediatorMapping +#ifdef LOG_LIFECYLE_MediatorMapping +# define LOG_LIFECYLE_MediatorMapping_emit(x) x + +#else +# define LOG_LIFECYLE_MediatorMapping_emit(x) + +#endif + + +using namespace com::sun::star; + +class MediatorMapping : public uno_Mapping +{ + oslInterlockedCount m_refCount; + + uno::Mapping m_from2uno; + uno::Mapping m_uno2to; + + uno::Environment m_from; + uno::Environment m_interm; + uno::Environment m_to; + +public: + void acquire(void); + void release(void); + + void mapInterface(void ** ppOut, + void * pInterface, + typelib_InterfaceTypeDescription * pInterfaceTypeDescr); + MediatorMapping(uno_Environment * pFrom, + uno_Environment * pInterm, + uno_Environment * pTo); + ~MediatorMapping(); +}; + +extern "C" { +static void SAL_CALL s_acquire(uno_Mapping * mapping) +{ + MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); + pMediatorMapping->acquire(); +} + +static void SAL_CALL s_release(uno_Mapping * mapping) +{ + MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); + pMediatorMapping->release(); +} + +static void SAL_CALL s_mapInterface( + uno_Mapping * mapping, + void ** ppOut, + void * pInterface, + typelib_InterfaceTypeDescription * pInterfaceTypeDescr) +{ + MediatorMapping * pMediatorMapping = static_cast<MediatorMapping *>(mapping); + pMediatorMapping->mapInterface(ppOut, pInterface, pInterfaceTypeDescr); +} +} + +MediatorMapping::MediatorMapping(uno_Environment * pFrom, + uno_Environment * pInterm, + uno_Environment * pTo) + : m_refCount(0), + m_from2uno(pFrom, pInterm), + m_uno2to (pInterm, pTo), + m_from (pFrom), + m_interm (pInterm), + m_to (pTo) +{ + LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); + + if (!m_from2uno.get() || !m_uno2to.get()) + abort(); + + uno_Mapping::acquire = s_acquire; + uno_Mapping::release = s_release; + uno_Mapping::mapInterface = s_mapInterface; +} + +MediatorMapping::~MediatorMapping() +{ + LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); +} + +void MediatorMapping::acquire(void) +{ + LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); + + osl_incrementInterlockedCount(&m_refCount); +} + +void MediatorMapping::release(void) +{ + LOG_LIFECYLE_MediatorMapping_emit(std::cerr << __FUNCTION__ << std::endl); + + if (osl_decrementInterlockedCount(&m_refCount) == 0) + { + ::uno_revokeMapping(this); + } +} + +extern "C" { static void s_mapInterface_v(va_list * pParam) +{ + void ** ppOut = va_arg(*pParam, void **); + void * pInterface = va_arg(*pParam, void *); + typelib_InterfaceTypeDescription * pInterfaceTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); + uno_Mapping * pMapping = va_arg(*pParam, uno_Mapping *); + + pMapping->mapInterface(pMapping, ppOut, pInterface, pInterfaceTypeDescr); +}} + +void MediatorMapping::mapInterface( + void ** ppOut, + void * pInterface, + typelib_InterfaceTypeDescription * pInterfaceTypeDescr) +{ + if (*ppOut != 0) + { + uno_ExtEnvironment * env = m_to.get()->pExtEnv; + OSL_ASSERT( env != 0 ); + env->releaseInterface( env, *ppOut ); + *ppOut = NULL; + } + + void * ret = 0; + uno_Interface * pUnoI = 0; + + m_from.invoke(s_mapInterface_v, &pUnoI, pInterface, pInterfaceTypeDescr, m_from2uno.get()); + + m_uno2to.mapInterface(&ret, pUnoI, pInterfaceTypeDescr); + + if (pUnoI) + m_interm.get()->pExtEnv->releaseInterface(m_interm.get()->pExtEnv, pUnoI); + + *ppOut = ret; +} + +extern "C" { static void SAL_CALL s_MediatorMapping_free(uno_Mapping * pMapping) + SAL_THROW_EXTERN_C() +{ + delete static_cast<MediatorMapping *>(pMapping); +}} + + + +static rtl::OUString getPrefix(rtl::OUString const & str1, rtl::OUString const & str2) +{ + sal_Int32 nIndex1 = 0; + sal_Int32 nIndex2 = 0; + sal_Int32 sim = 0; + + rtl::OUString token1; + rtl::OUString token2; + + do + { + token1 = str1.getToken(0, ':', nIndex1); + token2 = str2.getToken(0, ':', nIndex2); + + if (token1.equals(token2)) + sim += token1.getLength() + 1; + } + while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2)); + + rtl::OUString result; + + if (sim) + result = str1.copy(0, sim - 1); + + return result; +} + +// rtl::OUString str1(RTL_CONSTASCII_USTRINGPARAM("abc:def:ghi")); +// rtl::OUString str2(RTL_CONSTASCII_USTRINGPARAM("abc:def")); +// rtl::OUString str3(RTL_CONSTASCII_USTRINGPARAM("abc")); +// rtl::OUString str4(RTL_CONSTASCII_USTRINGPARAM("")); + +// rtl::OUString pref; + +// pref = getPrefix(str1, str1); +// pref = getPrefix(str1, str2); +// pref = getPrefix(str1, str3); +// pref = getPrefix(str1, str4); + +// pref = getPrefix(str2, str1); +// pref = getPrefix(str3, str1); +// pref = getPrefix(str4, str1); + + +void getCascadeMapping(uno_Mapping ** ppMapping, + uno_Environment * pFrom, + uno_Environment * pTo, + rtl_uString * pAddPurpose) +{ + if (pAddPurpose && pAddPurpose->length) + return; + + rtl::OUString uno_envType(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)); + + rtl::OUString from_envType = cppu::EnvDcp::getTypeName(pFrom->pTypeName); + rtl::OUString to_envType = cppu::EnvDcp::getTypeName(pTo->pTypeName); + rtl::OUString from_envPurpose = cppu::EnvDcp::getPurpose(pFrom->pTypeName); + rtl::OUString to_envPurpose = cppu::EnvDcp::getPurpose(pTo->pTypeName); + +#ifdef LOG_CALLING_named_purpose_getMapping + rtl::OString s_from_name = rtl::OUStringToOString(pFrom->pTypeName, RTL_TEXTENCODING_ASCII_US); + rtl::OString s_to_name = rtl::OUStringToOString(pTo->pTypeName, RTL_TEXTENCODING_ASCII_US); + + std::cerr << __FUNCTION__ << " - creating mediation "; + std::cerr << "pFrom: " << s_from_name.getStr(); + std::cerr <<" pTo: " << s_to_name.getStr() << std::endl; +#endif + + if (from_envPurpose == to_envPurpose) // gcc:bla => uno:bla + return; + + // reaching this point means, we need a mediated mapping!!! + // we generall mediate via uno[:free] + uno_Environment * pInterm = NULL; + + // chained uno -> uno + if (from_envType == uno_envType && to_envType == uno_envType) + { + rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); + + rtl::OUString uno_envDcp = uno_envType; + uno_envDcp += purpose; + + // direct mapping possible? + // uno:bla-->uno:bla:blubb + if (from_envPurpose.equals(purpose)) + { + rtl::OUString rest = to_envPurpose.copy(purpose.getLength()); + + sal_Int32 index = rest.indexOf(':', 1); + if (index == -1) + { + uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); + return; + } + + uno_envDcp += rest.copy(0, index); + } + else if (to_envPurpose.equals(purpose)) + { + rtl::OUString rest = from_envPurpose.copy(purpose.getLength()); + + sal_Int32 index = rest.indexOf(':', 1); + if (index == -1) + { + uno_getMapping(ppMapping, pFrom, pTo, rest.copy(1).pData); + return; + } + + uno_envDcp += rest.copy(0, index); + } + + uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); + } + else if (from_envType != uno_envType && to_envType == uno_envType) // <ANY> -> UNO ? + // mediate via uno:purpose(fromEnv) + { + rtl::OUString envDcp = uno_envType; + + envDcp += from_envPurpose; + uno_getEnvironment(&pInterm, envDcp.pData, NULL); + } + else if (from_envType == uno_envType && to_envType != uno_envType) // UNO -> <ANY>? + // mediate via uno(context) + { + rtl::OUString envDcp = uno_envType; + + envDcp += to_envPurpose; + uno_getEnvironment(&pInterm, envDcp.pData, NULL); + } + else // everything else + // mediate via uno:purpose + { + rtl::OUString purpose = getPrefix(from_envPurpose, to_envPurpose); + + rtl::OUString uno_envDcp = uno_envType; + uno_envDcp += purpose; + + uno_getEnvironment(&pInterm, uno_envDcp.pData, NULL); + } + + uno_Mapping * pMapping = new MediatorMapping(pFrom, pInterm, pTo); + pInterm->release(pInterm); + + + pMapping->acquire(pMapping); + + ::uno_registerMapping(&pMapping, s_MediatorMapping_free, pFrom, pTo, pAddPurpose); + + if (*ppMapping) + (*ppMapping)->release(*ppMapping); + + *ppMapping = pMapping; +} diff --git a/cppu/source/uno/cascade_mapping.hxx b/cppu/source/uno/cascade_mapping.hxx new file mode 100644 index 000000000000..3b63e17198fb --- /dev/null +++ b/cppu/source/uno/cascade_mapping.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_cascade_mapping_hxx +#define INCLUDED_cascade_mapping_hxx + +#include "uno/environment.h" +#include "uno/mapping.h" +#include "rtl/ustring.h" + + +void getCascadeMapping(uno_Mapping ** ppMapping, + uno_Environment * pFrom, + uno_Environment * pTo, + rtl_uString * pAddPurpose ); + +#endif diff --git a/cppu/source/uno/constr.hxx b/cppu/source/uno/constr.hxx new file mode 100644 index 000000000000..8e6d35e9db64 --- /dev/null +++ b/cppu/source/uno/constr.hxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CONSTR_HXX +#define CONSTR_HXX + +#include "prim.hxx" + + +namespace cppu +{ + +//################################################################################################## +//#### construction ################################################################################ +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +inline void _defaultConstructUnion( + void * pMem, + typelib_TypeDescription * pTypeDescr ) + SAL_THROW( () ) +{ + ::uno_type_constructData( + (char *)pMem + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + ((typelib_UnionTypeDescription *)pTypeDescr)->pDefaultTypeRef ); + *(sal_Int64 *)pMem = ((typelib_UnionTypeDescription *)pTypeDescr)->nDefaultDiscriminant; +} +//================================================================================================== +void defaultConstructStruct( + void * pMem, + typelib_CompoundTypeDescription * pCompType ) + SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +inline void _defaultConstructStruct( + void * pMem, + typelib_CompoundTypeDescription * pTypeDescr ) + SAL_THROW( () ) +{ + if (pTypeDescr->pBaseTypeDescription) + { + defaultConstructStruct( pMem, pTypeDescr->pBaseTypeDescription ); + } + + typelib_TypeDescriptionReference ** ppTypeRefs = (pTypeDescr)->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + + while (nDescr--) + { + ::uno_type_constructData( (char *)pMem + pMemberOffsets[nDescr], ppTypeRefs[nDescr] ); + } +} + +//-------------------------------------------------------------------------------------------------- +inline void _defaultConstructArray( + void * pMem, + typelib_ArrayTypeDescription * pTypeDescr ) +{ + typelib_TypeDescription * pElementType = NULL; + TYPELIB_DANGER_GET( &pElementType, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); + sal_Int32 nTotalElements = pTypeDescr->nTotalElements; + sal_Int32 nElementSize = pElementType->nSize; + sal_Int32 i; + switch ( pElementType->eTypeClass ) + { + case typelib_TypeClass_CHAR: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_INTERFACE: + ::rtl_zeroMemory(pMem, nElementSize * nTotalElements); + break; + + case typelib_TypeClass_STRING: + for (i=0; i < nTotalElements; i++) + { + rtl_uString** ppElement = (rtl_uString **)pMem + i; + *ppElement = 0; + rtl_uString_new( ppElement); + } + break; + case typelib_TypeClass_TYPE: + for (i=0; i < nTotalElements; i++) + { + typelib_TypeDescriptionReference** ppElement = (typelib_TypeDescriptionReference **)pMem + i; + *ppElement = _getVoidType(); + } + break; + case typelib_TypeClass_ANY: + for (i=0; i < nTotalElements; i++) + { + CONSTRUCT_EMPTY_ANY( (uno_Any *)pMem + i ); + } + break; + case typelib_TypeClass_ENUM: + for (i=0; i < nTotalElements; i++) + { + *((sal_Int32 *)pMem + i) = ((typelib_EnumTypeDescription *)pElementType)->nDefaultEnumValue; + } + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + for (i=0; i < nTotalElements; i++) + { + _defaultConstructStruct( (sal_Char*)pMem + i * nElementSize, (typelib_CompoundTypeDescription *)pElementType ); + } + break; + case typelib_TypeClass_UNION: + for (i=0; i < nTotalElements; i++) + { + _defaultConstructUnion( (sal_Char*)pMem + i * nElementSize, pElementType ); + } + break; + case typelib_TypeClass_SEQUENCE: + for (i=0; i < nTotalElements; i++) + { + uno_Sequence** ppElement = (uno_Sequence **)pMem + i; + *ppElement = createEmptySequence(); + } + break; + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE( pElementType ); +} + +//-------------------------------------------------------------------------------------------------- +inline void _defaultConstructData( + void * pMem, + typelib_TypeDescriptionReference * pType, + typelib_TypeDescription * pTypeDescr ) + SAL_THROW( () ) +{ + switch (pType->eTypeClass) + { + case typelib_TypeClass_CHAR: + *(sal_Unicode *)pMem = '\0'; + break; + case typelib_TypeClass_BOOLEAN: + *(sal_Bool *)pMem = sal_False; + break; + case typelib_TypeClass_BYTE: + *(sal_Int8 *)pMem = 0; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int16 *)pMem = 0; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_Int32 *)pMem = 0; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_Int64 *)pMem = 0; + break; + case typelib_TypeClass_FLOAT: + *(float *)pMem = 0.0; + break; + case typelib_TypeClass_DOUBLE: + *(double *)pMem = 0.0; + break; + case typelib_TypeClass_STRING: + *(rtl_uString **)pMem = 0; + ::rtl_uString_new( (rtl_uString **)pMem ); + break; + case typelib_TypeClass_TYPE: + *(typelib_TypeDescriptionReference **)pMem = _getVoidType(); + break; + case typelib_TypeClass_ANY: + CONSTRUCT_EMPTY_ANY( (uno_Any *)pMem ); + break; + case typelib_TypeClass_ENUM: + if (pTypeDescr) + { + *(sal_Int32 *)pMem = ((typelib_EnumTypeDescription *)pTypeDescr)->nDefaultEnumValue; + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + *(sal_Int32 *)pMem = ((typelib_EnumTypeDescription *)pTypeDescr)->nDefaultEnumValue; + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (pTypeDescr) + { + _defaultConstructStruct( pMem, (typelib_CompoundTypeDescription *)pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _defaultConstructStruct( pMem, (typelib_CompoundTypeDescription *)pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_ARRAY: + if (pTypeDescr) + { + _defaultConstructArray( pMem, (typelib_ArrayTypeDescription *)pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _defaultConstructArray( pMem, (typelib_ArrayTypeDescription *)pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_UNION: + if (pTypeDescr) + { + _defaultConstructUnion( pMem, pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _defaultConstructUnion( pMem, pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_SEQUENCE: + *(uno_Sequence **)pMem = createEmptySequence(); + break; + case typelib_TypeClass_INTERFACE: + *(void **)pMem = 0; // either cpp or c-uno interface + break; + default: + OSL_ASSERT(false); + break; + } +} + +} + +#endif diff --git a/cppu/source/uno/copy.hxx b/cppu/source/uno/copy.hxx new file mode 100644 index 000000000000..7999b5ae0d2b --- /dev/null +++ b/cppu/source/uno/copy.hxx @@ -0,0 +1,886 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef COPY_HXX +#define COPY_HXX + +#include "prim.hxx" +#include "constr.hxx" + + +namespace cppu +{ + +//################################################################################################## +//#### copy construction ########################################################################### +//################################################################################################## + +//------------------------------------------------------------------------------ +inline uno_Sequence * allocSeq( + sal_Int32 nElementSize, sal_Int32 nElements ) +{ + OSL_ASSERT( nElements >= 0 && nElementSize >= 0 ); + uno_Sequence * pSeq = 0; + sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements ); + if (nSize > 0) + { + pSeq = (uno_Sequence *) rtl_allocateMemory( nSize ); + if (pSeq != 0) + { + // header init + pSeq->nRefCount = 1; + pSeq->nElements = nElements; + } + } + return pSeq; +} + +//-------------------------------------------------------------------------------------------------- +void copyConstructStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ); +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ) +{ + if (pTypeDescr->pBaseTypeDescription) + { + // copy base value + copyConstructStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, acquire, mapping ); + } + + // then copy members + typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + + if (mapping) + { + while (nDescr--) + { + ::uno_type_copyAndConvertData( + (char *)pDest + pMemberOffsets[nDescr], + (char *)pSource + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], mapping ); + } + } + else + { + while (nDescr--) + { + ::uno_type_copyData( + (char *)pDest + pMemberOffsets[nDescr], + (char *)pSource + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], acquire ); + } + } +} +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructArray( + void * pDest, void * pSource, + typelib_ArrayTypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) +{ + typelib_TypeDescriptionReference * pElementTypeRef = ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; + typelib_TypeDescription * pElementTypeDescr = NULL; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementTypeRef ); + sal_Int32 nElementSize = ((typelib_TypeDescription*)pElementTypeDescr)->nSize; + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + sal_Int32 nTotalElements = pTypeDescr->nTotalElements; + + if (mapping) + { + for(sal_Int32 i = 0; i < nTotalElements; i++) + { + ::uno_type_copyAndConvertData( + (sal_Char *)pDest + i * nElementSize, + (sal_Char *)pSource + i * nElementSize, + pElementTypeRef, mapping ); + } + } + else + { + for(sal_Int32 i = 0; i < nTotalElements; i++) + { + ::uno_type_copyData( + (sal_Char *)pDest + (i * nElementSize), + (sal_Char *)pSource + (i * nElementSize), + pElementTypeRef, acquire ); + } + } +} +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructUnion( + void * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ) +{ + typelib_TypeDescriptionReference * pSetType = _unionGetSetType( pSource, pTypeDescr ); + if (mapping) + { + ::uno_type_copyAndConvertData( + (char *)pDest + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + (char *)pSource + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + pSetType, mapping ); + } + else + { + ::uno_type_copyData( + (char *)pDest + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + (char *)pSource + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + pSetType, acquire ); + } + *(sal_Int64 *)pDest = *(sal_Int64 *)pSource; + typelib_typedescriptionreference_release( pSetType ); +} + +//------------------------------------------------------------------------------ +uno_Sequence * copyConstructSequence( + uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_AcquireFunc acquire, uno_Mapping * mapping ); + +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructAnyFromData( + uno_Any * pDestAny, void * pSource, + typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ) +{ + TYPE_ACQUIRE( pType ); + pDestAny->pType = pType; + + switch (pType->eTypeClass) + { + case typelib_TypeClass_CHAR: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Unicode *)&pDestAny->pReserved = *(sal_Unicode *)pSource; + break; + case typelib_TypeClass_BOOLEAN: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Bool *)&pDestAny->pReserved = (*(sal_Bool *)pSource != sal_False); + break; + case typelib_TypeClass_BYTE: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int8 *)&pDestAny->pReserved = *(sal_Int8 *)pSource; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int16 *)&pDestAny->pReserved = *(sal_Int16 *)pSource; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int32 *)&pDestAny->pReserved = *(sal_Int32 *)pSource; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof(void *) >= sizeof(sal_Int64)) + { + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int64 *)&pDestAny->pReserved = *(sal_Int64 *)pSource; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(sal_Int64) ); + *(sal_Int64 *)pDestAny->pData = *(sal_Int64 *)pSource; + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof(void *) >= sizeof(float)) + { + pDestAny->pData = &pDestAny->pReserved; + *(float *)&pDestAny->pReserved = *(float *)pSource; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(float) ); + *(float *)pDestAny->pData = *(float *)pSource; + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof(void *) >= sizeof(double)) + { + pDestAny->pData = &pDestAny->pReserved; + *(double *)&pDestAny->pReserved = *(double *)pSource; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(double) ); + *(double *)pDestAny->pData = *(double *)pSource; + } + break; + case typelib_TypeClass_STRING: + ::rtl_uString_acquire( *(rtl_uString **)pSource ); + pDestAny->pData = &pDestAny->pReserved; + *(rtl_uString **)&pDestAny->pReserved = *(rtl_uString **)pSource; + break; + case typelib_TypeClass_TYPE: + TYPE_ACQUIRE( *(typelib_TypeDescriptionReference **)pSource ); + pDestAny->pData = &pDestAny->pReserved; + *(typelib_TypeDescriptionReference **)&pDestAny->pReserved = *(typelib_TypeDescriptionReference **)pSource; + break; + case typelib_TypeClass_ANY: + OSL_ENSURE( 0, "### unexpected nested any!" ); + break; + case typelib_TypeClass_ENUM: + pDestAny->pData = &pDestAny->pReserved; + // enum is forced to 32bit long + *(sal_Int32 *)&pDestAny->pReserved = *(sal_Int32 *)pSource; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructStruct( + pDestAny->pData, pSource, + (typelib_CompoundTypeDescription *)pTypeDescr, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructStruct( + pDestAny->pData, pSource, + (typelib_CompoundTypeDescription *)pTypeDescr, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_ARRAY: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructArray( + pDestAny->pData, pSource, + (typelib_ArrayTypeDescription *)pTypeDescr, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructArray( + pDestAny->pData, pSource, + (typelib_ArrayTypeDescription *)pTypeDescr, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_UNION: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructUnion( pDestAny->pData, pSource, pTypeDescr, acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _copyConstructUnion( pDestAny->pData, pSource, pTypeDescr, acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_SEQUENCE: + pDestAny->pData = &pDestAny->pReserved; + if (pTypeDescr) + { + *(uno_Sequence **)&pDestAny->pReserved = copyConstructSequence( + *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + *(uno_Sequence **)&pDestAny->pReserved = copyConstructSequence( + *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_INTERFACE: + pDestAny->pData = &pDestAny->pReserved; + if (mapping) + { + pDestAny->pReserved = _map( *(void **)pSource, pType, pTypeDescr, mapping ); + } + else + { + _acquire( pDestAny->pReserved = *(void **)pSource, acquire ); + } + break; + default: + OSL_ASSERT(false); + break; + } +} +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructAny( + uno_Any * pDestAny, void * pSource, + typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ) +{ + if (typelib_TypeClass_VOID == pType->eTypeClass) + { + CONSTRUCT_EMPTY_ANY( pDestAny ); + } + else + { + if (typelib_TypeClass_ANY == pType->eTypeClass) + { + if (pSource) + { + pType = ((uno_Any *)pSource)->pType; + if (typelib_TypeClass_VOID == pType->eTypeClass) + { + CONSTRUCT_EMPTY_ANY( pDestAny ); + return; + } + pTypeDescr = 0; + pSource = ((uno_Any *)pSource)->pData; + } + else + { + CONSTRUCT_EMPTY_ANY( pDestAny ); + return; + } + } + if (pSource) + { + _copyConstructAnyFromData( pDestAny, pSource, pType, pTypeDescr, acquire, mapping ); + } + else // default construct + { + TYPE_ACQUIRE( pType ); + pDestAny->pType = pType; + switch (pType->eTypeClass) + { + case typelib_TypeClass_CHAR: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Unicode *)&pDestAny->pReserved = '\0'; + break; + case typelib_TypeClass_BOOLEAN: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Bool *)&pDestAny->pReserved = sal_False; + break; + case typelib_TypeClass_BYTE: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int8 *)&pDestAny->pReserved = 0; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int16 *)&pDestAny->pReserved = 0; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int32 *)&pDestAny->pReserved = 0; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof(void *) >= sizeof(sal_Int64)) + { + pDestAny->pData = &pDestAny->pReserved; + *(sal_Int64 *)&pDestAny->pReserved = 0; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(sal_Int64) ); + *(sal_Int64 *)pDestAny->pData = 0; + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof(void *) >= sizeof(float)) + { + pDestAny->pData = &pDestAny->pReserved; + *(float *)&pDestAny->pReserved = 0.0; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(float) ); + *(float *)pDestAny->pData = 0.0; + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof(void *) >= sizeof(double)) + { + pDestAny->pData = &pDestAny->pReserved; + *(double *)&pDestAny->pReserved = 0.0; + } + else + { + pDestAny->pData = ::rtl_allocateMemory( sizeof(double) ); + *(double *)pDestAny->pData = 0.0; + } + break; + case typelib_TypeClass_STRING: + pDestAny->pData = &pDestAny->pReserved; + *(rtl_uString **)&pDestAny->pReserved = 0; + ::rtl_uString_new( (rtl_uString **)&pDestAny->pReserved ); + break; + case typelib_TypeClass_TYPE: + pDestAny->pData = &pDestAny->pReserved; + *(typelib_TypeDescriptionReference **)&pDestAny->pReserved = _getVoidType(); + break; + case typelib_TypeClass_ENUM: + pDestAny->pData = &pDestAny->pReserved; + if (pTypeDescr) + { + *(sal_Int32 *)&pDestAny->pReserved = ((typelib_EnumTypeDescription *)pTypeDescr)->nDefaultEnumValue; + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + *(sal_Int32 *)&pDestAny->pReserved = ((typelib_EnumTypeDescription *)pTypeDescr)->nDefaultEnumValue; + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructStruct( + pDestAny->pData, (typelib_CompoundTypeDescription *)pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructStruct( + pDestAny->pData, (typelib_CompoundTypeDescription *)pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_ARRAY: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructArray( + pDestAny->pData, (typelib_ArrayTypeDescription *)pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructArray( + pDestAny->pData, (typelib_ArrayTypeDescription *)pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_UNION: + if (pTypeDescr) + { + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructUnion( pDestAny->pData, pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); + _defaultConstructUnion( pDestAny->pData, pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_SEQUENCE: + pDestAny->pData = &pDestAny->pReserved; + *(uno_Sequence **)&pDestAny->pReserved = createEmptySequence(); + break; + case typelib_TypeClass_INTERFACE: + pDestAny->pData = &pDestAny->pReserved; + pDestAny->pReserved = 0; // either cpp or c-uno interface + break; + default: + OSL_ASSERT(false); + break; + } + } + } +} +//------------------------------------------------------------------------------ +inline uno_Sequence * icopyConstructSequence( + uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_AcquireFunc acquire, uno_Mapping * mapping ) +{ + typelib_TypeClass eTypeClass = pElementType->eTypeClass; + if (!mapping || + (eTypeClass <= typelib_TypeClass_ENUM && + eTypeClass != typelib_TypeClass_ANY)) + { + ::osl_incrementInterlockedCount( &pSource->nRefCount ); + return pSource; + } + else // create new sequence + { + uno_Sequence * pDest; + sal_Int32 nElements = pSource->nElements; + if (nElements) + { + switch (eTypeClass) + { + case typelib_TypeClass_ANY: + { + pDest = allocSeq( sizeof (uno_Any), nElements ); + if (pDest != 0) + { + uno_Any * pDestElements = (uno_Any *)pDest->elements; + uno_Any * pSourceElements = (uno_Any *)pSource->elements; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + typelib_TypeDescriptionReference * pType = + pSourceElements[nPos].pType; + if (typelib_TypeClass_VOID == pType->eTypeClass) + { + CONSTRUCT_EMPTY_ANY( &pDestElements[nPos] ); + } + else + { + _copyConstructAnyFromData( + &pDestElements[nPos], + pSourceElements[nPos].pData, + pType, 0, + acquire, mapping ); + } + } + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + char * pSourceElements = pSource->elements; + pDest = allocSeq( nElementSize, nElements ); + if (pDest != 0) + { + char * pElements = pDest->elements; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + _copyConstructStruct( + pElements + (nPos * nElementSize), + pSourceElements + (nPos * nElementSize), + (typelib_CompoundTypeDescription *) + pElementTypeDescr, + acquire, mapping ); + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_ARRAY: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + char * pSourceElements = pSource->elements; + pDest = allocSeq( nElementSize, nElements ); + if (pDest != 0) + { + char * pElements = pDest->elements; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + _copyConstructArray( + pElements + (nPos * nElementSize), + pSourceElements + (nPos * nElementSize), + (typelib_ArrayTypeDescription *)pElementTypeDescr, + acquire, mapping ); + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + sal_Int32 nValueOffset = + ((typelib_UnionTypeDescription *) + pElementTypeDescr)->nValueOffset; + pDest = allocSeq( nElementSize, nElements ); + if (pDest != 0) + { + char * pElements = pDest->elements; + char * pSourceElements = pSource->elements; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + char * pDest2 = + pElements + (nPos * nElementSize); + char * pSource2 = + pSourceElements + (nPos * nElementSize); + + typelib_TypeDescriptionReference * pSetType = + _unionGetSetType( pSource2, pElementTypeDescr ); + ::uno_type_copyAndConvertData( + pDest2 + nValueOffset, pSource2 + nValueOffset, + pSetType, mapping ); + *(sal_Int64 *)pDest2 = *(sal_Int64 *)pSource2; + ::typelib_typedescriptionreference_release( pSetType ); + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_SEQUENCE: // sequence of sequence + { + pDest = allocSeq( sizeof (uno_Sequence *), nElements ); + if (pDest != 0) + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + typelib_TypeDescriptionReference * pSeqElementType = + ((typelib_IndirectTypeDescription *) + pElementTypeDescr)->pType; + + uno_Sequence ** pDestElements = + (uno_Sequence **) pDest->elements; + uno_Sequence ** pSourceElements = + (uno_Sequence **) pSource->elements; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + uno_Sequence * pNew = copyConstructSequence( + pSourceElements[nPos], + pSeqElementType, + acquire, mapping ); + OSL_ASSERT( pNew != 0 ); + // ought never be a memory allocation problem, + // because of reference counted sequence handles + pDestElements[ nPos ] = pNew; + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + } + break; + } + case typelib_TypeClass_INTERFACE: + { + pDest = allocSeq( sizeof (void *), nElements ); + if (pDest != 0) + { + char * pElements = pDest->elements; + void ** pSourceElements = (void **)pSource->elements; + if (mapping) + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + for ( sal_Int32 nPos = nElements; nPos--; ) + { + ((void **)pElements)[nPos] = 0; + if (((void **)pSourceElements)[nPos]) + { + (*mapping->mapInterface)( + mapping, (void **)pElements + nPos, + pSourceElements[nPos], + (typelib_InterfaceTypeDescription *) + pElementTypeDescr ); + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + } + else + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + ((void **)pElements)[nPos] = pSourceElements[nPos]; + _acquire( ((void **)pElements)[nPos], acquire ); + } + } + } + break; + } + default: + OSL_ENSURE( 0, "### unexepcted sequence element type!" ); + pDest = 0; + break; + } + } + else // empty sequence + { + pDest = allocSeq( 0, 0 ); + } + + return pDest; + } +} + +//-------------------------------------------------------------------------------------------------- +inline void _copyConstructData( + void * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW ( () ) +{ + switch (pType->eTypeClass) + { + case typelib_TypeClass_CHAR: + *(sal_Unicode *)pDest = *(sal_Unicode *)pSource; + break; + case typelib_TypeClass_BOOLEAN: + *(sal_Bool *)pDest = (*(sal_Bool *)pSource != sal_False); + break; + case typelib_TypeClass_BYTE: + *(sal_Int8 *)pDest = *(sal_Int8 *)pSource; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int16 *)pDest = *(sal_Int16 *)pSource; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + *(sal_Int32 *)pDest = *(sal_Int32 *)pSource; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_Int64 *)pDest = *(sal_Int64 *)pSource; + break; + case typelib_TypeClass_FLOAT: + *(float *)pDest = *(float *)pSource; + break; + case typelib_TypeClass_DOUBLE: + *(double *)pDest = *(double *)pSource; + break; + case typelib_TypeClass_STRING: + ::rtl_uString_acquire( *(rtl_uString **)pSource ); + *(rtl_uString **)pDest = *(rtl_uString **)pSource; + break; + case typelib_TypeClass_TYPE: + TYPE_ACQUIRE( *(typelib_TypeDescriptionReference **)pSource ); + *(typelib_TypeDescriptionReference **)pDest = *(typelib_TypeDescriptionReference **)pSource; + break; + case typelib_TypeClass_ANY: + _copyConstructAny( + (uno_Any *)pDest, ((uno_Any *)pSource)->pData, + ((uno_Any *)pSource)->pType, 0, + acquire, mapping ); + break; + case typelib_TypeClass_ENUM: + *(sal_Int32 *)pDest = *(sal_Int32 *)pSource; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (pTypeDescr) + { + _copyConstructStruct( + pDest, pSource, + (typelib_CompoundTypeDescription *)pTypeDescr, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _copyConstructStruct( + pDest, pSource, + (typelib_CompoundTypeDescription *)pTypeDescr, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_ARRAY: + if (pTypeDescr) + { + _copyConstructArray( + pDest, pSource, + (typelib_ArrayTypeDescription *)pTypeDescr, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _copyConstructArray( + pDest, pSource, + (typelib_ArrayTypeDescription *)pTypeDescr, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_UNION: + if (pTypeDescr) + { + _copyConstructUnion( pDest, pSource, pTypeDescr, acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _copyConstructUnion( pDest, pSource, pTypeDescr, acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_SEQUENCE: + if (mapping) + { + if (pTypeDescr) + { + *(uno_Sequence **)pDest = icopyConstructSequence( + *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + acquire, mapping ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + *(uno_Sequence **)pDest = icopyConstructSequence( + *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + acquire, mapping ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + } + else + { + ::osl_incrementInterlockedCount( &(*(uno_Sequence **)pSource)->nRefCount ); + *(uno_Sequence **)pDest = *(uno_Sequence **)pSource; + } + break; + case typelib_TypeClass_INTERFACE: + if (mapping) + *(void **)pDest = _map( *(void **)pSource, pType, pTypeDescr, mapping ); + else + _acquire( *(void **)pDest = *(void **)pSource, acquire ); + break; + default: + break; + } +} + +} + +#endif diff --git a/cppu/source/uno/data.cxx b/cppu/source/uno/data.cxx new file mode 100644 index 000000000000..5b29637b581b --- /dev/null +++ b/cppu/source/uno/data.cxx @@ -0,0 +1,617 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" + +#include "cppu/macros.hxx" + +#include "osl/mutex.hxx" + +#include "constr.hxx" +#include "destr.hxx" +#include "copy.hxx" +#include "assign.hxx" +#include "eq.hxx" + +#include "boost/static_assert.hpp" + + +using namespace ::cppu; +using namespace ::rtl; +using namespace ::osl; + + +namespace cppu +{ + +// Sequence<>() (default ctor) relies on this being static: +uno_Sequence g_emptySeq = { 1, 0, { 0 } }; +typelib_TypeDescriptionReference * g_pVoidType = 0; + +//-------------------------------------------------------------------------------------------------- +void * binuno_queryInterface( void * pUnoI, typelib_TypeDescriptionReference * pDestType ) +{ + // init queryInterface() td + static typelib_TypeDescription * g_pQITD = 0; + if (0 == g_pQITD) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (0 == g_pQITD) + { + typelib_TypeDescriptionReference * type_XInterface = + * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ); + typelib_InterfaceTypeDescription * pTXInterfaceDescr = 0; + TYPELIB_DANGER_GET( (typelib_TypeDescription **) &pTXInterfaceDescr, type_XInterface ); + OSL_ASSERT( pTXInterfaceDescr->ppAllMembers ); + typelib_typedescriptionreference_getDescription( + &g_pQITD, pTXInterfaceDescr->ppAllMembers[ 0 ] ); + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *) pTXInterfaceDescr ); + } + } + + uno_Any aRet, aExc; + uno_Any * pExc = &aExc; + void * aArgs[ 1 ]; + aArgs[ 0 ] = &pDestType; + (*((uno_Interface *) pUnoI)->pDispatcher)( + (uno_Interface *) pUnoI, g_pQITD, &aRet, aArgs, &pExc ); + + uno_Interface * ret = 0; + if (0 == pExc) + { + typelib_TypeDescriptionReference * ret_type = aRet.pType; + switch (ret_type->eTypeClass) + { + case typelib_TypeClass_VOID: // common case + typelib_typedescriptionreference_release( ret_type ); + break; + case typelib_TypeClass_INTERFACE: + // tweaky... avoiding acquire/ release pair + typelib_typedescriptionreference_release( ret_type ); + ret = (uno_Interface *) aRet.pReserved; // serving acquired interface + break; + default: + _destructAny( &aRet, 0 ); + break; + } + } + else + { +#if OSL_DEBUG_LEVEL > 1 + OUStringBuffer buf( 128 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("### exception occured querying for interface ") ); + buf.append( * reinterpret_cast< OUString const * >( &pDestType->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": [") ); + buf.append( * reinterpret_cast< OUString const * >( &pExc->pType->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + // Message is very first member + buf.append( * reinterpret_cast< OUString const * >( pExc->pData ) ); + OString cstr( + OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_ENSURE( 0, cstr.getStr() ); +#endif + uno_any_destruct( pExc, 0 ); + } + return ret; +} + +//================================================================================================== +void defaultConstructStruct( + void * pMem, + typelib_CompoundTypeDescription * pCompType ) + SAL_THROW( () ) +{ + _defaultConstructStruct( pMem, pCompType ); +} +//================================================================================================== +void copyConstructStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_Mapping * mapping ) + SAL_THROW( () ) +{ + _copyConstructStruct( pDest, pSource, pTypeDescr, acquire, mapping ); +} +//================================================================================================== +void destructStruct( + void * pValue, + typelib_CompoundTypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + _destructStruct( pValue, pTypeDescr, release ); +} +//================================================================================================== +sal_Bool equalStruct( + void * pDest, void *pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + return _equalStruct( pDest, pSource, pTypeDescr, queryInterface, release ); +} +//================================================================================================== +sal_Bool assignStruct( + void * pDest, void * pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + return _assignStruct( pDest, pSource, pTypeDescr, queryInterface, acquire, release ); +} + +//============================================================================== +uno_Sequence * copyConstructSequence( + uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_AcquireFunc acquire, uno_Mapping * mapping ) +{ + return icopyConstructSequence( pSource, pElementType, acquire, mapping ); +} + +//============================================================================== +void destructSequence( + uno_Sequence * pSequence, + typelib_TypeDescriptionReference * pType, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) +{ + idestructSequence( pSequence, pType, pTypeDescr, release ); +} + +//================================================================================================== +sal_Bool equalSequence( + uno_Sequence * pDest, uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + return _equalSequence( pDest, pSource, pElementType, queryInterface, release ); +} + +extern "C" +{ +//################################################################################################## +void SAL_CALL uno_type_constructData( + void * pMem, typelib_TypeDescriptionReference * pType ) + SAL_THROW_EXTERN_C() +{ + _defaultConstructData( pMem, pType, 0 ); +} +//################################################################################################## +void SAL_CALL uno_constructData( + void * pMem, typelib_TypeDescription * pTypeDescr ) + SAL_THROW_EXTERN_C() +{ + _defaultConstructData( pMem, pTypeDescr->pWeakRef, pTypeDescr ); +} +//################################################################################################## +void SAL_CALL uno_type_destructData( + void * pValue, typelib_TypeDescriptionReference * pType, + uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructData( pValue, pType, 0, release ); +} +//################################################################################################## +void SAL_CALL uno_destructData( + void * pValue, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + _destructData( pValue, pTypeDescr->pWeakRef, pTypeDescr, release ); +} +//################################################################################################## +void SAL_CALL uno_type_copyData( + void * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + _copyConstructData( pDest, pSource, pType, 0, acquire, 0 ); +} +//################################################################################################## +void SAL_CALL uno_copyData( + void * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + _copyConstructData( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, acquire, 0 ); +} +//################################################################################################## +void SAL_CALL uno_type_copyAndConvertData( + void * pDest, void * pSource, + typelib_TypeDescriptionReference * pType, + uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + _copyConstructData( pDest, pSource, pType, 0, 0, mapping ); +} +//################################################################################################## +void SAL_CALL uno_copyAndConvertData( + void * pDest, void * pSource, + typelib_TypeDescription * pTypeDescr, + uno_Mapping * mapping ) + SAL_THROW_EXTERN_C() +{ + _copyConstructData( pDest, pSource, pTypeDescr->pWeakRef, pTypeDescr, 0, mapping ); +} +//################################################################################################## +sal_Bool SAL_CALL uno_type_equalData( + void * pVal1, typelib_TypeDescriptionReference * pVal1Type, + void * pVal2, typelib_TypeDescriptionReference * pVal2Type, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + return _equalData( + pVal1, pVal1Type, 0, + pVal2, pVal2Type, 0, + queryInterface, release ); +} +//################################################################################################## +sal_Bool SAL_CALL uno_equalData( + void * pVal1, typelib_TypeDescription * pVal1TD, + void * pVal2, typelib_TypeDescription * pVal2TD, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + return _equalData( + pVal1, pVal1TD->pWeakRef, pVal1TD, + pVal2, pVal2TD->pWeakRef, pVal2TD, + queryInterface, release ); +} +//################################################################################################## +sal_Bool SAL_CALL uno_type_assignData( + void * pDest, typelib_TypeDescriptionReference * pDestType, + void * pSource, typelib_TypeDescriptionReference * pSourceType, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + return _assignData( + pDest, pDestType, 0, + pSource, pSourceType, 0, + queryInterface, acquire, release ); +} +//################################################################################################## +sal_Bool SAL_CALL uno_assignData( + void * pDest, typelib_TypeDescription * pDestTD, + void * pSource, typelib_TypeDescription * pSourceTD, + uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + return _assignData( + pDest, pDestTD->pWeakRef, pDestTD, + pSource, pSourceTD->pWeakRef, pSourceTD, + queryInterface, acquire, release ); +} +//################################################################################################## +sal_Bool SAL_CALL uno_type_isAssignableFromData( + typelib_TypeDescriptionReference * pAssignable, + void * pFrom, typelib_TypeDescriptionReference * pFromType, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + if (::typelib_typedescriptionreference_isAssignableFrom( pAssignable, pFromType )) + return sal_True; + if (typelib_TypeClass_INTERFACE != pFromType->eTypeClass || + typelib_TypeClass_INTERFACE != pAssignable->eTypeClass) + { + return sal_False; + } + + // query + if (0 == pFrom) + return sal_False; + void * pInterface = *(void **)pFrom; + if (0 == pInterface) + return sal_False; + + if (0 == queryInterface) + queryInterface = binuno_queryInterface; + void * p = (*queryInterface)( pInterface, pAssignable ); + _release( p, release ); + return (0 != p); +} +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +#if OSL_DEBUG_LEVEL > 1 + +#include <stdio.h> + +#if defined( SAL_W32) +#pragma pack(push, 8) +#elif defined(SAL_OS2) +#pragma pack(push, 4) +#endif + +#if defined(INTEL) \ + && (defined(__GNUC__) && (defined(LINUX) || defined(FREEBSD) || defined(OS2)) || defined(MACOSX) \ + || defined(__SUNPRO_CC) && defined(SOLARIS)) +#define MAX_ALIGNMENT_4 +#endif + +#define OFFSET_OF( s, m ) ((sal_Size)((char *)&((s *)16)->m -16)) + +#define BINTEST_VERIFY( c ) \ + if (! (c)) { fprintf( stderr, "### binary compatibility test failed: " #c " [line %d]!!!\n", __LINE__ ); abort(); } +#define BINTEST_VERIFYOFFSET( s, m, n ) \ + if (OFFSET_OF(s, m) != n) { fprintf( stderr, "### OFFSET_OF(" #s ", " #m ") = %d instead of expected %d!!!\n", OFFSET_OF(s, m), n ); abort(); } + +#if OSL_DEBUG_LEVEL > 1 +#if defined(__GNUC__) && (defined(LINUX) || defined(FREEBSD)) && (defined(INTEL) || defined(POWERPC) || defined(X86_64) || defined(S390)) +#define BINTEST_VERIFYSIZE( s, n ) \ + fprintf( stderr, "> sizeof(" #s ") = %d; __alignof__ (" #s ") = %d\n", sizeof(s), __alignof__ (s) ); \ + if (sizeof(s) != n) { fprintf( stderr, "### sizeof(" #s ") = %d instead of expected %d!!!\n", sizeof(s), n ); abort(); } +#else // ! GNUC +#define BINTEST_VERIFYSIZE( s, n ) \ + fprintf( stderr, "> sizeof(" #s ") = %d\n", sizeof(s) ); \ + if (sizeof(s) != n) { fprintf( stderr, "### sizeof(" #s ") = %d instead of expected %d!!!\n", sizeof(s), n ); abort(); } +#endif +#else // ! OSL_DEBUG_LEVEL +#define BINTEST_VERIFYSIZE( s, n ) \ + if (sizeof(s) != n) { fprintf( stderr, "### sizeof(" #s ") = %d instead of expected %d!!!\n", sizeof(s), n ); abort(); } +#endif + +struct C1 +{ + sal_Int16 n1; +}; +struct C2 : public C1 +{ + sal_Int32 n2 CPPU_GCC3_ALIGN( C1 ); +}; +struct C3 : public C2 +{ + double d3; + sal_Int32 n3; +}; +struct C4 : public C3 +{ + sal_Int32 n4 CPPU_GCC3_ALIGN( C3 ); + double d4; +}; +struct C5 : public C4 +{ + sal_Int64 n5; + sal_Bool b5; +}; +struct C6 : public C1 +{ + C5 c6 CPPU_GCC3_ALIGN( C1 ); + sal_Bool b6; +}; + +struct D +{ + sal_Int16 d; + sal_Int32 e; +}; +struct E +{ + sal_Bool a; + sal_Bool b; + sal_Bool c; + sal_Int16 d; + sal_Int32 e; +}; + +struct M +{ + sal_Int32 n; + sal_Int16 o; +}; + +struct N : public M +{ + sal_Int16 p CPPU_GCC3_ALIGN( M ); +}; +struct N2 +{ + M m; + sal_Int16 p; +}; + +struct O : public M +{ + double p; + sal_Int16 q; +}; +struct O2 : public O +{ + sal_Int16 p2 CPPU_GCC3_ALIGN( O ); +}; + +struct P : public N +{ + double p2; +}; + +struct empty +{ +}; +struct second : public empty +{ + int a; +}; + +struct AlignSize_Impl +{ + sal_Int16 nInt16; + double dDouble; +}; + +struct Char1 +{ + char c1; +}; +struct Char2 : public Char1 +{ + char c2 CPPU_GCC3_ALIGN( Char1 ); +}; +struct Char3 : public Char2 +{ + char c3 CPPU_GCC3_ALIGN( Char2 ); +}; +struct Char4 +{ + Char3 chars; + char c; +}; +class Ref +{ + void * p; +}; +enum Enum +{ + v = SAL_MAX_ENUM +}; + + +class BinaryCompatible_Impl +{ +public: + BinaryCompatible_Impl(); +}; +BinaryCompatible_Impl::BinaryCompatible_Impl() +{ + BOOST_STATIC_ASSERT( ((sal_Bool) true) == sal_True && + (1 != 0) == sal_True ); + BOOST_STATIC_ASSERT( ((sal_Bool) false) == sal_False && + (1 == 0) == sal_False ); +#ifdef MAX_ALIGNMENT_4 + // max alignment is 4 + BINTEST_VERIFYOFFSET( AlignSize_Impl, dDouble, 4 ); + BINTEST_VERIFYSIZE( AlignSize_Impl, 12 ); +#else + // max alignment is 8 + BINTEST_VERIFYOFFSET( AlignSize_Impl, dDouble, 8 ); + BINTEST_VERIFYSIZE( AlignSize_Impl, 16 ); +#endif + + // sequence + BINTEST_VERIFY( (SAL_SEQUENCE_HEADER_SIZE % 8) == 0 ); + // enum + BINTEST_VERIFY( sizeof( Enum ) == sizeof( sal_Int32 ) ); + // any + BINTEST_VERIFY( sizeof(void *) >= sizeof(sal_Int32) ); + BINTEST_VERIFY( sizeof( uno_Any ) == sizeof( void * ) * 3 ); + BINTEST_VERIFYOFFSET( uno_Any, pType, 0 ); + BINTEST_VERIFYOFFSET( uno_Any, pData, 1 * sizeof (void *) ); + BINTEST_VERIFYOFFSET( uno_Any, pReserved, 2 * sizeof (void *) ); + // interface + BINTEST_VERIFY( sizeof( Ref ) == sizeof( void * ) ); + // string + BINTEST_VERIFY( sizeof( OUString ) == sizeof( rtl_uString * ) ); + // struct + BINTEST_VERIFYSIZE( M, 8 ); + BINTEST_VERIFYOFFSET( M, o, 4 ); + BINTEST_VERIFYSIZE( N, 12 ); + BINTEST_VERIFYOFFSET( N, p, 8 ); + BINTEST_VERIFYSIZE( N2, 12 ); + BINTEST_VERIFYOFFSET( N2, p, 8 ); +#ifdef MAX_ALIGNMENT_4 + BINTEST_VERIFYSIZE( O, 20 ); +#else + BINTEST_VERIFYSIZE( O, 24 ); +#endif + BINTEST_VERIFYSIZE( D, 8 ); + BINTEST_VERIFYOFFSET( D, e, 4 ); + BINTEST_VERIFYOFFSET( E, d, 4 ); + BINTEST_VERIFYOFFSET( E, e, 8 ); + + BINTEST_VERIFYSIZE( C1, 2 ); + BINTEST_VERIFYSIZE( C2, 8 ); + BINTEST_VERIFYOFFSET( C2, n2, 4 ); + +#ifdef MAX_ALIGNMENT_4 + BINTEST_VERIFYSIZE( C3, 20 ); + BINTEST_VERIFYOFFSET( C3, d3, 8 ); + BINTEST_VERIFYOFFSET( C3, n3, 16 ); + BINTEST_VERIFYSIZE( C4, 32 ); + BINTEST_VERIFYOFFSET( C4, n4, 20 ); + BINTEST_VERIFYOFFSET( C4, d4, 24 ); + BINTEST_VERIFYSIZE( C5, 44 ); + BINTEST_VERIFYOFFSET( C5, n5, 32 ); + BINTEST_VERIFYOFFSET( C5, b5, 40 ); + BINTEST_VERIFYSIZE( C6, 52 ); + BINTEST_VERIFYOFFSET( C6, c6, 4 ); + BINTEST_VERIFYOFFSET( C6, b6, 48 ); + + BINTEST_VERIFYSIZE( O2, 24 ); + BINTEST_VERIFYOFFSET( O2, p2, 20 ); +#else + BINTEST_VERIFYSIZE( C3, 24 ); + BINTEST_VERIFYOFFSET( C3, d3, 8 ); + BINTEST_VERIFYOFFSET( C3, n3, 16 ); + BINTEST_VERIFYSIZE( C4, 40 ); + BINTEST_VERIFYOFFSET( C4, n4, 24 ); + BINTEST_VERIFYOFFSET( C4, d4, 32 ); + BINTEST_VERIFYSIZE( C5, 56 ); + BINTEST_VERIFYOFFSET( C5, n5, 40 ); + BINTEST_VERIFYOFFSET( C5, b5, 48 ); + BINTEST_VERIFYSIZE( C6, 72 ); + BINTEST_VERIFYOFFSET( C6, c6, 8 ); + BINTEST_VERIFYOFFSET( C6, b6, 64 ); + + BINTEST_VERIFYSIZE( O2, 32 ); + BINTEST_VERIFYOFFSET( O2, p2, 24 ); +#endif + + BINTEST_VERIFYSIZE( Char3, 3 ); + BINTEST_VERIFYOFFSET( Char4, c, 3 ); + +#ifdef MAX_ALIGNMENT_4 + // max alignment is 4 + BINTEST_VERIFYSIZE( P, 20 ); +#else + // alignment of P is 8, because of P[] ... + BINTEST_VERIFYSIZE( P, 24 ); + BINTEST_VERIFYSIZE( second, sizeof( int ) ); +#endif +} + +#ifdef SAL_W32 +# pragma pack(pop) +#elif defined(SAL_OS2) +# pragma pack() +#endif + +static BinaryCompatible_Impl aTest; + +#endif + +} diff --git a/cppu/source/uno/destr.hxx b/cppu/source/uno/destr.hxx new file mode 100644 index 000000000000..8f156038ade5 --- /dev/null +++ b/cppu/source/uno/destr.hxx @@ -0,0 +1,438 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef DESTR_HXX +#define DESTR_HXX + +#include "prim.hxx" + + +namespace cppu +{ + +//################################################################################################## +//#### destruction ################################################################################# +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +inline void _destructUnion( + void * pValue, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + typelib_TypeDescriptionReference * pType = _unionGetSetType( pValue, pTypeDescr ); + ::uno_type_destructData( + (char *)pValue + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset, + pType, release ); + ::typelib_typedescriptionreference_release( pType ); +} +//================================================================================================== +void destructStruct( + void * pValue, + typelib_CompoundTypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +inline void _destructStruct( + void * pValue, + typelib_CompoundTypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pTypeDescr->pBaseTypeDescription) + { + destructStruct( pValue, pTypeDescr->pBaseTypeDescription, release ); + } + + typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + while (nDescr--) + { + ::uno_type_destructData( + (char *)pValue + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], release ); + } +} + +//-------------------------------------------------------------------------------------------------- +inline void _destructArray( + void * pValue, + typelib_ArrayTypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + throw () +{ + typelib_TypeDescription * pElementType = NULL; + TYPELIB_DANGER_GET( &pElementType, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); + sal_Int32 nElementSize = pElementType->nSize; + TYPELIB_DANGER_RELEASE( pElementType ); + + sal_Int32 nTotalElements = pTypeDescr->nTotalElements; + for(sal_Int32 i=0; i < nTotalElements; i++) + { + ::uno_type_destructData( + (sal_Char *)pValue + i * nElementSize, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, release ); + } + + typelib_typedescriptionreference_release(((typelib_IndirectTypeDescription *)pTypeDescr)->pType); +} + +//============================================================================== +void destructSequence( + uno_Sequence * pSequence, + typelib_TypeDescriptionReference * pType, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ); + +//-------------------------------------------------------------------------------------------------- +inline void _destructAny( + uno_Any * pAny, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + typelib_TypeDescriptionReference * pType = pAny->pType; + + switch (pType->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (sizeof(void *) < sizeof(sal_Int64)) + { + ::rtl_freeMemory( pAny->pData ); + } + break; + case typelib_TypeClass_FLOAT: + if (sizeof(void *) < sizeof(float)) + { + ::rtl_freeMemory( pAny->pData ); + } + break; + case typelib_TypeClass_DOUBLE: + if (sizeof(void *) < sizeof(double)) + { + ::rtl_freeMemory( pAny->pData ); + } + break; + case typelib_TypeClass_STRING: + ::rtl_uString_release( (rtl_uString *)pAny->pReserved ); + break; + case typelib_TypeClass_TYPE: + ::typelib_typedescriptionreference_release( + (typelib_TypeDescriptionReference *)pAny->pReserved ); + break; + case typelib_TypeClass_ANY: + OSL_ENSURE( sal_False, "### unexpected nested any!" ); + ::uno_any_destruct( (uno_Any *)pAny->pData, release ); + ::rtl_freeMemory( pAny->pData ); + break; + case typelib_TypeClass_TYPEDEF: + OSL_ENSURE( 0, "### unexpected typedef!" ); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _destructStruct( pAny->pData, (typelib_CompoundTypeDescription *)pTypeDescr, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + ::rtl_freeMemory( pAny->pData ); + break; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _destructUnion( pAny->pData, pTypeDescr, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + ::rtl_freeMemory( pAny->pData ); + break; + } + case typelib_TypeClass_SEQUENCE: + { + destructSequence( + *(uno_Sequence **) &pAny->pReserved, pType, 0, release ); + break; + } + case typelib_TypeClass_INTERFACE: + _release( pAny->pReserved, release ); + break; + default: + break; + } +#if OSL_DEBUG_LEVEL > 0 + pAny->pData = (void *)0xdeadbeef; +#endif + + ::typelib_typedescriptionreference_release( pType ); +} +//-------------------------------------------------------------------------------------------------- +inline sal_Int32 idestructElements( + void * pElements, typelib_TypeDescriptionReference * pElementType, + sal_Int32 nStartIndex, sal_Int32 nStopIndex, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + switch (pElementType->eTypeClass) + { + case typelib_TypeClass_CHAR: + return (sal_Int32)(sizeof(sal_Unicode)); + case typelib_TypeClass_BOOLEAN: + return (sal_Int32)(sizeof(sal_Bool)); + case typelib_TypeClass_BYTE: + return (sal_Int32)(sizeof(sal_Int8)); + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + return (sal_Int32)(sizeof(sal_Int16)); + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + return (sal_Int32)(sizeof(sal_Int32)); + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + return (sal_Int32)(sizeof(sal_Int64)); + case typelib_TypeClass_FLOAT: + return (sal_Int32)(sizeof(float)); + case typelib_TypeClass_DOUBLE: + return (sal_Int32)(sizeof(double)); + + case typelib_TypeClass_STRING: + { + rtl_uString ** pDest = (rtl_uString **)pElements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + ::rtl_uString_release( pDest[nPos] ); + } + return (sal_Int32)(sizeof(rtl_uString *)); + } + case typelib_TypeClass_TYPE: + { + typelib_TypeDescriptionReference ** pDest = (typelib_TypeDescriptionReference **)pElements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + ::typelib_typedescriptionreference_release( pDest[nPos] ); + } + return (sal_Int32)(sizeof(typelib_TypeDescriptionReference *)); + } + case typelib_TypeClass_ANY: + { + uno_Any * pDest = (uno_Any *)pElements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _destructAny( &pDest[nPos], release ); + } + return (sal_Int32)(sizeof(uno_Any)); + } + case typelib_TypeClass_ENUM: + return (sal_Int32)(sizeof(sal_Int32)); + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _destructStruct( + (char *)pElements + (nElementSize * nPos), + (typelib_CompoundTypeDescription *)pElementTypeDescr, + release ); + } + sal_Int32 nSize = pElementTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return nSize; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _destructUnion( + (char *)pElements + (nElementSize * nPos), + pElementTypeDescr, + release ); + } + sal_Int32 nSize = pElementTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return nSize; + } + case typelib_TypeClass_SEQUENCE: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + uno_Sequence ** pDest = (uno_Sequence **)pElements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + destructSequence( + pDest[nPos], + pElementTypeDescr->pWeakRef, pElementTypeDescr, + release ); + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return (sal_Int32)(sizeof(uno_Sequence *)); + } + case typelib_TypeClass_INTERFACE: + { + if (release) + { + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + void * p = ((void **)pElements)[nPos]; + if (p) + { + (*release)( p ); + } + } + } + else + { + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + uno_Interface * p = ((uno_Interface **)pElements)[nPos]; + if (p) + { + (*p->release)( p ); + } + } + } + return (sal_Int32)(sizeof(void *)); + } + default: + OSL_ASSERT(false); + return 0; + } +} + +//------------------------------------------------------------------------------ +inline void idestructSequence( + uno_Sequence * pSeq, + typelib_TypeDescriptionReference * pType, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) +{ + if (::osl_decrementInterlockedCount( &pSeq->nRefCount ) == 0) + { + if (pSeq->nElements > 0) + { + if (pTypeDescr) + { + idestructElements( + pSeq->elements, + ((typelib_IndirectTypeDescription *) pTypeDescr)->pType, 0, + pSeq->nElements, release ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + idestructElements( + pSeq->elements, + ((typelib_IndirectTypeDescription *) pTypeDescr)->pType, 0, + pSeq->nElements, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + } + ::rtl_freeMemory( pSeq ); + } +} + +//-------------------------------------------------------------------------------------------------- +inline void _destructData( + void * pValue, + typelib_TypeDescriptionReference * pType, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + switch (pType->eTypeClass) + { + case typelib_TypeClass_STRING: + ::rtl_uString_release( *(rtl_uString **)pValue ); + break; + case typelib_TypeClass_TYPE: + ::typelib_typedescriptionreference_release( *(typelib_TypeDescriptionReference **)pValue ); + break; + case typelib_TypeClass_ANY: + _destructAny( (uno_Any *)pValue, release ); + break; + case typelib_TypeClass_TYPEDEF: + OSL_ENSURE( 0, "### unexpected typedef!" ); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (pTypeDescr) + { + _destructStruct( pValue, (typelib_CompoundTypeDescription *)pTypeDescr, release ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _destructStruct( pValue, (typelib_CompoundTypeDescription *)pTypeDescr, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_ARRAY: + if (pTypeDescr) + { + _destructArray( pValue, (typelib_ArrayTypeDescription *)pTypeDescr, release ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _destructArray( pValue, (typelib_ArrayTypeDescription *)pTypeDescr, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_UNION: + if (pTypeDescr) + { + _destructUnion( pValue, pTypeDescr, release ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + _destructUnion( pValue, pTypeDescr, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + case typelib_TypeClass_SEQUENCE: + { + idestructSequence( + *(uno_Sequence **)pValue, pType, pTypeDescr, release ); + break; + } + case typelib_TypeClass_INTERFACE: + _release( *(void **)pValue, release ); + break; + default: + break; + } +} + +} + +#endif diff --git a/cppu/source/uno/env_subst.cxx b/cppu/source/uno/env_subst.cxx new file mode 100644 index 000000000000..4465a9e1815e --- /dev/null +++ b/cppu/source/uno/env_subst.cxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "rtl/ustring.hxx" +#include "uno/environment.h" +#include "env_subst.hxx" + + +void SAL_CALL uno_getEnvironment(uno_Environment ** ppEnv, + rtl_uString * pEnvDcp, + void * pContext) + SAL_THROW_EXTERN_C() +{ + rtl::OUString envDcp(pEnvDcp); + + rtl::OString a_envName("UNO_ENV_SUBST:"); + a_envName += rtl::OUStringToOString(envDcp, RTL_TEXTENCODING_ASCII_US); + char * c_value = getenv(a_envName.getStr()); + if (c_value && rtl_str_getLength(c_value)) + { + rtl::OString a_envDcp(a_envName.copy(a_envName.indexOf(':') + 1)); + + OSL_TRACE("UNO_ENV_SUBST \"%s\" -> \"%s\"", a_envDcp.getStr(), c_value); + rtl::OUString value(c_value, rtl_str_getLength(c_value), RTL_TEXTENCODING_ASCII_US); + + envDcp = value; + } + + uno_direct_getEnvironment(ppEnv, envDcp.pData, pContext); +} diff --git a/cppu/source/uno/env_subst.hxx b/cppu/source/uno/env_subst.hxx new file mode 100644 index 000000000000..8ee8631ced84 --- /dev/null +++ b/cppu/source/uno/env_subst.hxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_env_substs_hxx +#define INCLUDED_env_substs_hxx + +#include "rtl/ustring.hxx" +#include "uno/environment.h" + + +extern "C" void SAL_CALL uno_direct_getEnvironment(uno_Environment ** ppEnv, + rtl_uString * pEnvDcp, + void * pContext) + SAL_THROW_EXTERN_C(); + + +#endif diff --git a/cppu/source/uno/eq.hxx b/cppu/source/uno/eq.hxx new file mode 100644 index 000000000000..45bc0e79cfaa --- /dev/null +++ b/cppu/source/uno/eq.hxx @@ -0,0 +1,668 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef EQ_HXX +#define EQ_HXX + +#include <math.h> +#include <rtl/memory.h> + +#include "prim.hxx" +#include "destr.hxx" + + +namespace cppu +{ + +//################################################################################################## +//#### equality #################################################################################### +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _equalObject( + void * pI1, void * pI2, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pI1 == pI2) + return sal_True; + if ((0 == pI1) || (0 == pI2)) + return sal_False; + sal_Bool bRet = sal_False; + + typelib_TypeDescriptionReference * type_XInterface = + * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ); + if (0 == queryInterface) + queryInterface = binuno_queryInterface; + pI1 = (*queryInterface)( pI1, type_XInterface ); + if (0 != pI1) + { + pI2 = (*queryInterface)( pI2, type_XInterface ); + if (0 != pI2) + { + bRet = (pI1 == pI2); + _release( pI2, release ); + } + _release( pI1, release ); + } + return bRet; +} + +//================================================================================================== +sal_Bool equalStruct( + void * pDest, void *pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _equalStruct( + void * pDest, void *pSource, + typelib_CompoundTypeDescription * pTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pTypeDescr->pBaseTypeDescription && + !equalStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, queryInterface, release )) + { + return sal_False; + } + + typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + + while (nDescr--) + { + sal_Int32 nOffset = pMemberOffsets[nDescr]; + if (! ::uno_type_equalData( (char *)pDest + nOffset, + ppTypeRefs[nDescr], + (char *)pSource + nOffset, + ppTypeRefs[nDescr], + queryInterface, release )) + { + return sal_False; + } + } + return sal_True; +} +//================================================================================================== +sal_Bool equalSequence( + uno_Sequence * pDest, uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _equalSequence( + uno_Sequence * pDest, uno_Sequence * pSource, + typelib_TypeDescriptionReference * pElementType, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + if (pDest == pSource) + return sal_True; + sal_Int32 nElements = pDest->nElements; + if (nElements != pSource->nElements) + return sal_False; + if (! nElements) + return sal_True; + + void * pDestElements = pDest->elements; + void * pSourceElements = pSource->elements; + + switch (pElementType->eTypeClass) + { + case typelib_TypeClass_CHAR: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Unicode) * nElements )); + case typelib_TypeClass_BOOLEAN: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if ((((sal_Bool *)pDestElements)[nPos] != sal_False) != + (((sal_Bool *)pSourceElements)[nPos] != sal_False)) + { + return sal_False; + } + } + return sal_True; + } + case typelib_TypeClass_BYTE: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Int8) * nElements )); + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Int16) * nElements )); + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Int32) * nElements )); + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Int64) * nElements )); + case typelib_TypeClass_FLOAT: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (((float *)pDestElements)[nPos] != ((float *)pSourceElements)[nPos]) + return sal_False; + } + return sal_True; + } + case typelib_TypeClass_DOUBLE: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (((double *)pDestElements)[nPos] != ((double *)pSourceElements)[nPos]) + return sal_False; + } + return sal_True; + } + case typelib_TypeClass_STRING: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (! ((::rtl::OUString *)pDestElements +nPos)->equals( ((const ::rtl::OUString *)pSourceElements)[nPos] )) + return sal_False; + } + return sal_True; + } + case typelib_TypeClass_TYPE: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (! _type_equals( ((typelib_TypeDescriptionReference **)pDestElements)[nPos], + ((typelib_TypeDescriptionReference **)pSourceElements)[nPos] )) + { + return sal_False; + } + } + return sal_True; + } + case typelib_TypeClass_ANY: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + uno_Any * pDest2 = (uno_Any *)pDestElements + nPos; + uno_Any * pSource2 = (uno_Any *)pSourceElements + nPos; + if (! ::uno_type_equalData( pDest2->pData, pDest2->pType, + pSource2->pData, pSource2->pType, + queryInterface, release )) + { + return sal_False; + } + } + return sal_True; + } + case typelib_TypeClass_ENUM: + return (0 == ::rtl_compareMemory( pDestElements, pSourceElements, sizeof(sal_Int32) * nElements )); + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (! _equalStruct( (char *)pDestElements + (nPos * nElementSize), + (char *)pSourceElements + (nPos * nElementSize), + (typelib_CompoundTypeDescription *)pElementTypeDescr, + queryInterface, release )) + { + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_False; + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_True; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + sal_Int32 nValueOffset = ((typelib_UnionTypeDescription *)pElementTypeDescr)->nValueOffset; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + char * pDest2 = (char *)pDestElements + (nPos * nElementSize); + char * pSource2 = (char *)pSourceElements + (nPos * nElementSize); + typelib_TypeDescriptionReference * pSetType = _unionGetSetType( + pDest2, pElementTypeDescr ); + sal_Bool bRet = ::uno_type_equalData( + pDest2 + nValueOffset, pSetType, + pSource2 + nValueOffset, pSetType, + queryInterface, release ); + ::typelib_typedescriptionreference_release( pSetType ); + if (! bRet) + { + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_False; + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_True; + } + case typelib_TypeClass_SEQUENCE: // sequence of sequence + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + typelib_TypeDescriptionReference * pSeqElementType = + ((typelib_IndirectTypeDescription *)pElementTypeDescr)->pType; + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (! equalSequence( ((uno_Sequence **)pDestElements)[nPos], + ((uno_Sequence **)pSourceElements)[nPos], + pSeqElementType, queryInterface, release )) + { + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_False; + } + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + return sal_True; + } + case typelib_TypeClass_INTERFACE: + { + for ( sal_Int32 nPos = nElements; nPos--; ) + { + if (! _equalObject( ((void **)pDestElements)[nPos], ((void **)pSourceElements)[nPos], + queryInterface, release )) + { + return sal_False; + } + } + return sal_True; + } + default: + OSL_ASSERT(false); + return sal_False; + } +} +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _equalData( + void * pDest, + typelib_TypeDescriptionReference * pDestType, typelib_TypeDescription * pDestTypeDescr, + void * pSource, + typelib_TypeDescriptionReference * pSourceType, typelib_TypeDescription * pSourceTypeDescr, + uno_QueryInterfaceFunc queryInterface, uno_ReleaseFunc release ) + SAL_THROW( () ) +{ + typelib_TypeClass eSourceTypeClass, eDestTypeClass; + while (typelib_TypeClass_ANY == (eDestTypeClass = pDestType->eTypeClass)) + { + pDestTypeDescr = 0; + pDestType = ((uno_Any *)pDest)->pType; + pDest = ((uno_Any *)pDest)->pData; + } + while (typelib_TypeClass_ANY == (eSourceTypeClass = pSourceType->eTypeClass)) + { + pSourceTypeDescr = 0; + pSourceType = ((uno_Any *)pSource)->pType; + pSource = ((uno_Any *)pSource)->pData; + } + + switch (eDestTypeClass) + { + case typelib_TypeClass_VOID: + return eSourceTypeClass == typelib_TypeClass_VOID; + case typelib_TypeClass_CHAR: + return eSourceTypeClass == typelib_TypeClass_CHAR + && *(sal_Unicode *)pDest == *(sal_Unicode *)pSource; + case typelib_TypeClass_BOOLEAN: + return eSourceTypeClass == typelib_TypeClass_BOOLEAN + && ((*(sal_Bool *)pDest != sal_False) + == (*(sal_Bool *)pSource != sal_False)); + case typelib_TypeClass_BYTE: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(sal_Int8 *)pDest == *(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return ((sal_Int16)*(sal_Int8 *)pDest == *(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return ((sal_Int32)*(sal_Int8 *)pDest == (sal_Int32)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return ((sal_Int32)*(sal_Int8 *)pDest == *(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return ((sal_Int64)*(sal_Int8 *)pDest == (sal_Int64)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return ((sal_Int64)*(sal_Int8 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return (*(sal_Int8 *)pDest >= 0 && + (sal_Int64)*(sal_Int8 *)pDest == *(sal_Int64 *)pSource); // same size + case typelib_TypeClass_FLOAT: + return ((float)*(sal_Int8 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_Int8 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_SHORT: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(sal_Int16 *)pDest == (sal_Int16)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(sal_Int16 *)pDest == *(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return ((sal_Int32)*(sal_Int16 *)pDest == (sal_Int32)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return ((sal_Int32)*(sal_Int16 *)pDest == *(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return ((sal_Int64)*(sal_Int16 *)pDest == (sal_Int64)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return ((sal_Int64)*(sal_Int16 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return (*(sal_Int16 *)pDest >= 0 && + (sal_Int64)*(sal_Int16 *)pDest == *(sal_Int64 *)pSource); // same size + case typelib_TypeClass_FLOAT: + return ((float)*(sal_Int16 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_Int16 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_SHORT: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return ((sal_Int32)*(sal_uInt16 *)pDest == (sal_Int32)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return ((sal_Int32)*(sal_uInt16 *)pDest == (sal_Int32)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(sal_uInt16 *)pDest == *(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return ((sal_Int32)*(sal_uInt16 *)pDest == *(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return ((sal_uInt32)*(sal_uInt16 *)pDest == *(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return ((sal_Int64)*(sal_uInt16 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return ((sal_uInt64)*(sal_uInt16 *)pDest == *(sal_uInt64 *)pSource); + case typelib_TypeClass_FLOAT: + return ((float)*(sal_uInt16 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_uInt16 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_LONG: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(sal_Int32 *)pDest == (sal_Int32)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(sal_Int32 *)pDest == (sal_Int32)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(sal_Int32 *)pDest == (sal_Int32)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return (*(sal_Int32 *)pDest == *(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return ((sal_Int64)*(sal_Int32 *)pDest == (sal_Int64)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return ((sal_Int64)*(sal_Int32 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return (*(sal_Int32 *)pDest >= 0 && + (sal_Int64)*(sal_Int32 *)pDest == *(sal_Int64 *)pSource); // same size + case typelib_TypeClass_FLOAT: + return ((float)*(sal_Int32 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_Int32 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_LONG: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return ((sal_Int64)*(sal_uInt32 *)pDest == (sal_Int64)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return ((sal_Int64)*(sal_uInt32 *)pDest == (sal_Int64)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(sal_uInt32 *)pDest == (sal_uInt32)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return ((sal_Int64)*(sal_uInt32 *)pDest == (sal_Int64)*(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return (*(sal_uInt32 *)pDest == *(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return ((sal_Int64)*(sal_uInt32 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return ((sal_uInt64)*(sal_uInt32 *)pDest == *(sal_uInt64 *)pSource); + case typelib_TypeClass_FLOAT: + return ((float)*(sal_uInt32 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_uInt32 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_HYPER: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(sal_Int64 *)pDest == (sal_Int64)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(sal_Int64 *)pDest == (sal_Int64)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(sal_Int64 *)pDest == (sal_Int64)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return (*(sal_Int64 *)pDest == (sal_Int64)*(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return (*(sal_Int64 *)pDest == (sal_Int64)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return (*(sal_Int64 *)pDest == *(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return (*(sal_Int64 *)pDest >= 0 && + *(sal_Int64 *)pDest == *(sal_Int64 *)pSource); // same size + case typelib_TypeClass_FLOAT: + return ((float)*(sal_Int64 *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(sal_Int64 *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_UNSIGNED_HYPER: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(sal_Int8 *)pSource >= 0 && + *(sal_uInt64 *)pDest == (sal_uInt64)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(sal_Int16 *)pSource >= 0 && + *(sal_uInt64 *)pDest == (sal_uInt64)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(sal_uInt64 *)pDest == (sal_uInt64)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return (*(sal_Int32 *)pSource >= 0 && + *(sal_uInt64 *)pDest == (sal_uInt64)*(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return (*(sal_uInt64 *)pDest == (sal_uInt64)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return (*(sal_Int64 *)pSource >= 0 && + *(sal_uInt64 *)pDest == (sal_uInt64)*(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + return (*(sal_uInt64 *)pDest == *(sal_uInt64 *)pSource); + case typelib_TypeClass_FLOAT: + if (::floor( *(float *)pSource ) != *(float *)pSource || *(float *)pSource < 0) + return sal_False; + return (*(sal_uInt64 *)pDest == (sal_uInt64)*(float *)pSource); + case typelib_TypeClass_DOUBLE: + if (::floor( *(double *)pSource ) != *(double *)pSource || *(double *)pSource < 0) + return sal_False; + return (*(sal_uInt64 *)pDest == (sal_uInt64)*(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_FLOAT: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(float *)pDest == (float)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(float *)pDest == (float)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(float *)pDest == (float)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return (*(float *)pDest == (float)*(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return (*(float *)pDest == (float)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return (*(float *)pDest == (float)*(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + if (::floor( *(float *)pDest ) != *(float *)pDest || *(float *)pDest < 0) + return sal_False; + return ((sal_uInt64)*(float *)pDest == *(sal_uInt64 *)pSource); + case typelib_TypeClass_FLOAT: + return (*(float *)pDest == *(float *)pSource); + case typelib_TypeClass_DOUBLE: + return ((double)*(float *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_DOUBLE: + switch (eSourceTypeClass) + { + case typelib_TypeClass_BYTE: + return (*(double *)pDest == (double)*(sal_Int8 *)pSource); + case typelib_TypeClass_SHORT: + return (*(double *)pDest == (double)*(sal_Int16 *)pSource); + case typelib_TypeClass_UNSIGNED_SHORT: + return (*(double *)pDest == (double)*(sal_uInt16 *)pSource); + case typelib_TypeClass_LONG: + return (*(double *)pDest == (double)*(sal_Int32 *)pSource); + case typelib_TypeClass_UNSIGNED_LONG: + return (*(double *)pDest == (double)*(sal_uInt32 *)pSource); + case typelib_TypeClass_HYPER: + return (*(double *)pDest == (double)*(sal_Int64 *)pSource); + case typelib_TypeClass_UNSIGNED_HYPER: + if (::floor( *(double *)pDest ) != *(double *)pDest || *(double *)pDest < 0) + return sal_False; + return ((sal_uInt64)*(double *)pDest == *(sal_uInt64 *)pSource); + case typelib_TypeClass_FLOAT: + return (*(double *)pDest == (double)*(float *)pSource); + case typelib_TypeClass_DOUBLE: + return (*(double *)pDest == *(double *)pSource); + default: + return sal_False; + } + case typelib_TypeClass_STRING: + return eSourceTypeClass == typelib_TypeClass_STRING + && ((::rtl::OUString *)pDest)->equals( + *(::rtl::OUString const *)pSource ); + case typelib_TypeClass_TYPE: + return eSourceTypeClass == typelib_TypeClass_TYPE + && _type_equals( + *(typelib_TypeDescriptionReference **)pDest, + *(typelib_TypeDescriptionReference **)pSource ); + case typelib_TypeClass_ENUM: + return (_type_equals( pDestType, pSourceType ) && + *(sal_Int32 *)pDest == *(sal_Int32 *)pSource); + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (! _type_equals( pDestType, pSourceType )) + return sal_False; + if (pDestTypeDescr) + { + return _equalStruct( + pDest, pSource, + (typelib_CompoundTypeDescription *)pDestTypeDescr, + queryInterface, release ); + } + else + { + TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType ); + sal_Bool bRet = _equalStruct( + pDest, pSource, + (typelib_CompoundTypeDescription *)pDestTypeDescr, + queryInterface, release ); + TYPELIB_DANGER_RELEASE( pDestTypeDescr ); + return bRet; + } + case typelib_TypeClass_UNION: + if (_type_equals( pDestType, pSourceType ) && + *(sal_Int64 *)pDest == *(sal_Int64 *)pSource) // same discriminant + { + sal_Bool bRet; + if (pDestTypeDescr) + { + typelib_TypeDescriptionReference * pSetType = _unionGetSetType( + pDest, pDestTypeDescr ); + bRet = ::uno_type_equalData( + (char *)pDest + ((typelib_UnionTypeDescription *)pDestTypeDescr)->nValueOffset, + pSetType, + (char *)pSource + ((typelib_UnionTypeDescription *)pDestTypeDescr)->nValueOffset, + pSetType, + queryInterface, release ); + typelib_typedescriptionreference_release( pSetType ); + } + else + { + TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType ); + typelib_TypeDescriptionReference * pSetType = _unionGetSetType( + pDest, pDestTypeDescr ); + bRet = ::uno_type_equalData( + (char *)pDest + ((typelib_UnionTypeDescription *)pDestTypeDescr)->nValueOffset, + pSetType, + (char *)pSource + ((typelib_UnionTypeDescription *)pDestTypeDescr)->nValueOffset, + pSetType, + queryInterface, release ); + typelib_typedescriptionreference_release( pSetType ); + TYPELIB_DANGER_RELEASE( pDestTypeDescr ); + } + return bRet; + } + return sal_False; + case typelib_TypeClass_SEQUENCE: + if (_type_equals( pDestType, pSourceType )) + { + if (pDestTypeDescr) + { + return _equalSequence( + *(uno_Sequence **)pDest, *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pDestTypeDescr)->pType, + queryInterface, release ); + } + else + { + TYPELIB_DANGER_GET( &pDestTypeDescr, pDestType ); + sal_Bool bRet = _equalSequence( + *(uno_Sequence **)pDest, *(uno_Sequence **)pSource, + ((typelib_IndirectTypeDescription *)pDestTypeDescr)->pType, + queryInterface, release ); + TYPELIB_DANGER_RELEASE( pDestTypeDescr ); + return bRet; + } + } + return sal_False; + case typelib_TypeClass_INTERFACE: + if (typelib_TypeClass_INTERFACE == eSourceTypeClass) + return _equalObject( *(void **)pDest, *(void **)pSource, queryInterface, release ); + break; + default: + OSL_ASSERT(false); + break; + } + return sal_False; +} + +} + +#endif diff --git a/cppu/source/uno/lbenv.cxx b/cppu/source/uno/lbenv.cxx new file mode 100644 index 000000000000..21d16c5b9148 --- /dev/null +++ b/cppu/source/uno/lbenv.cxx @@ -0,0 +1,1182 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" + +#include "cppu/EnvDcp.hxx" + +#include "sal/alloca.h" +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "osl/mutex.hxx" +#include "osl/module.h" +#include "osl/process.h" +#include "rtl/process.h" +#include "rtl/unload.h" +#include "rtl/string.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/instance.hxx" +#include "typelib/typedescription.h" +#include "uno/dispatcher.h" +#include "uno/environment.h" +#include "uno/lbnames.h" +#include "prim.hxx" +#include "destr.hxx" +#include "loadmodule.hxx" + +#include <hash_map> +#include <vector> +#include <stdio.h> + + +using ::rtl::OUString; + +namespace +{ + +//------------------------------------------------------------------------------ +inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1, + typelib_InterfaceTypeDescription * pTD2 ) +{ + return (pTD1 == pTD2 || + (((typelib_TypeDescription *)pTD1)->pTypeName->length == + ((typelib_TypeDescription *)pTD2)->pTypeName->length && + ::rtl_ustr_compare( + ((typelib_TypeDescription *) pTD1)->pTypeName->buffer, + ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0)); +} + +struct ObjectEntry; +struct uno_DefaultEnvironment; + +//------------------------------------------------------------------------------ +struct InterfaceEntry +{ + sal_Int32 refCount; + void * pInterface; + uno_freeProxyFunc fpFreeProxy; + typelib_InterfaceTypeDescription * pTypeDescr; +}; + +struct ObjectEntry +{ + OUString oid; + sal_Int32 nRef; + ::std::vector< InterfaceEntry > aInterfaces; + bool mixedObject; + + inline ObjectEntry( const OUString & rOId_ ); + + inline void append( + uno_DefaultEnvironment * pEnv, + void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, + uno_freeProxyFunc fpFreeProxy ); + inline InterfaceEntry * find( + typelib_InterfaceTypeDescription * pTypeDescr ); + inline sal_Int32 find( void * iface_ptr, ::std::size_t pos ); +}; + +//------------------------------------------------------------------------------ +struct FctPtrHash : + public ::std::unary_function< const void *, ::std::size_t > +{ + ::std::size_t operator () ( const void * pKey ) const + { return (::std::size_t) pKey; } +}; + +//------------------------------------------------------------------------------ +struct FctOUStringHash : + public ::std::unary_function< const OUString &, ::std::size_t > +{ + ::std::size_t operator () ( const OUString & rKey ) const + { return rKey.hashCode(); } +}; + +// mapping from environment name to environment +typedef ::std::hash_map< + OUString, uno_Environment *, FctOUStringHash, + ::std::equal_to< OUString > > OUString2EnvironmentMap; + +// mapping from ptr to object entry +typedef ::std::hash_map< + void *, ObjectEntry *, FctPtrHash, + ::std::equal_to< void * > > Ptr2ObjectMap; +// mapping from oid to object entry +typedef ::std::hash_map< + OUString, ObjectEntry *, FctOUStringHash, + ::std::equal_to< OUString > > OId2ObjectMap; + + +//============================================================================== +struct EnvironmentsData +{ + ::osl::Mutex mutex; + OUString2EnvironmentMap aName2EnvMap; + + ~EnvironmentsData(); + + inline void getEnvironment( + uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ); + inline void registerEnvironment( uno_Environment ** ppEnv ); + inline void getRegisteredEnvironments( + uno_Environment *** pppEnvs, sal_Int32 * pnLen, + uno_memAlloc memAlloc, const OUString & rEnvDcp ); +}; + +namespace +{ + struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {}; +} + +//============================================================================== +struct uno_DefaultEnvironment : public uno_ExtEnvironment +{ + sal_Int32 nRef; + sal_Int32 nWeakRef; + + ::osl::Mutex mutex; + Ptr2ObjectMap aPtr2ObjectMap; + OId2ObjectMap aOId2ObjectMap; + + uno_DefaultEnvironment( + const OUString & rEnvDcp_, void * pContext_ ); + ~uno_DefaultEnvironment(); +}; + +//______________________________________________________________________________ +inline ObjectEntry::ObjectEntry( OUString const & rOId_ ) + : oid( rOId_ ), + nRef( 0 ), + mixedObject( false ) +{ + aInterfaces.reserve( 2 ); +} + +//______________________________________________________________________________ +inline void ObjectEntry::append( + uno_DefaultEnvironment * pEnv, + void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, + uno_freeProxyFunc fpFreeProxy ) +{ + InterfaceEntry aNewEntry; + if (! fpFreeProxy) + (*pEnv->acquireInterface)( pEnv, pInterface ); + aNewEntry.refCount = 1; + aNewEntry.pInterface = pInterface; + aNewEntry.fpFreeProxy = fpFreeProxy; + typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr ); + aNewEntry.pTypeDescr = pTypeDescr; + + ::std::pair< Ptr2ObjectMap::iterator, bool > insertion( + pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type( + pInterface, this ) ) ); + OSL_ASSERT( insertion.second || + (find( pInterface, 0 ) >= 0 && + // points to the same object entry: + insertion.first->second == this) ); + aInterfaces.push_back( aNewEntry ); +} + +//______________________________________________________________________________ +inline InterfaceEntry * ObjectEntry::find( + typelib_InterfaceTypeDescription * pTypeDescr_ ) +{ + OSL_ASSERT( ! aInterfaces.empty() ); + if (aInterfaces.empty()) + return 0; + + // shortcut common case: + OUString const & type_name = + OUString::unacquired( + &((typelib_TypeDescription *) pTypeDescr_)->pTypeName ); + if (type_name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) + { + return &aInterfaces[ 0 ]; + } + + ::std::size_t nSize = aInterfaces.size(); + for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos ) + { + typelib_InterfaceTypeDescription * pITD = + aInterfaces[ nPos ].pTypeDescr; + while (pITD) + { + if (td_equals( pITD, pTypeDescr_ )) + return &aInterfaces[ nPos ]; + pITD = pITD->pBaseTypeDescription; + } + } + return 0; +} + +//______________________________________________________________________________ +inline sal_Int32 ObjectEntry::find( + void * iface_ptr, ::std::size_t pos ) +{ + ::std::size_t size = aInterfaces.size(); + for ( ; pos < size; ++pos ) + { + if (aInterfaces[ pos ].pInterface == iface_ptr) + return pos; + } + return -1; +} + +extern "C" +{ + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_registerInterface( + uno_ExtEnvironment * pEnv, void ** ppInterface, + rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) +{ + OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); + OUString const & rOId = OUString::unacquired( &pOId ); + + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::ClearableMutexGuard guard( that->mutex ); + + // try to insert dummy 0: + std::pair<OId2ObjectMap::iterator, bool> const insertion( + that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); + if (insertion.second) + { + ObjectEntry * pOEntry = new ObjectEntry( rOId ); + insertion.first->second = pOEntry; + ++pOEntry->nRef; // another register call on object + pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); + } + else // object entry exists + { + ObjectEntry * pOEntry = insertion.first->second; + ++pOEntry->nRef; // another register call on object + InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); + + if (pIEntry) // type entry exists + { + ++pIEntry->refCount; + if (pIEntry->pInterface != *ppInterface) + { + void * pInterface = pIEntry->pInterface; + (*pEnv->acquireInterface)( pEnv, pInterface ); + guard.clear(); + (*pEnv->releaseInterface)( pEnv, *ppInterface ); + *ppInterface = pInterface; + } + } + else + { + pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); + } + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_registerProxyInterface( + uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy, + rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) +{ + OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy, + "### null ptr!" ); + OUString const & rOId = OUString::unacquired( &pOId ); + + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::ClearableMutexGuard guard( that->mutex ); + + // try to insert dummy 0: + std::pair<OId2ObjectMap::iterator, bool> const insertion( + that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); + if (insertion.second) + { + ObjectEntry * pOEntry = new ObjectEntry( rOId ); + insertion.first->second = pOEntry; + ++pOEntry->nRef; // another register call on object + pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); + } + else // object entry exists + { + ObjectEntry * pOEntry = insertion.first->second; + + // first registration was an original, then registerProxyInterface(): + pOEntry->mixedObject |= + (!pOEntry->aInterfaces.empty() && + pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0); + + ++pOEntry->nRef; // another register call on object + InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); + + if (pIEntry) // type entry exists + { + if (pIEntry->pInterface == *ppInterface) + { + ++pIEntry->refCount; + } + else + { + void * pInterface = pIEntry->pInterface; + (*pEnv->acquireInterface)( pEnv, pInterface ); + --pOEntry->nRef; // manual revoke of proxy to be freed + guard.clear(); + (*freeProxy)( pEnv, *ppInterface ); + *ppInterface = pInterface; + } + } + else + { + pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); + } + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam) +{ + uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + + OSL_ENSURE( pEnv && pInterface, "### null ptr!" ); + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::ClearableMutexGuard guard( that->mutex ); + + Ptr2ObjectMap::const_iterator const iFind( + that->aPtr2ObjectMap.find( pInterface ) ); + OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() ); + ObjectEntry * pOEntry = iFind->second; + if (! --pOEntry->nRef) + { + // cleanup maps + that->aOId2ObjectMap.erase( pOEntry->oid ); + sal_Int32 nPos; + for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) + { + that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface ); + } + + // the last proxy interface of the environment might kill this + // environment, because of releasing its language binding!!! + guard.clear(); + + // release interfaces + for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) + { + InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos]; + typelib_typedescription_release( + (typelib_TypeDescription *) rEntry.pTypeDescr ); + if (rEntry.fpFreeProxy) // is proxy or used interface? + { + (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface ); + } + else + { + (*pEnv->releaseInterface)( pEnv, rEntry.pInterface ); + } + } + + delete pOEntry; + } + else if (pOEntry->mixedObject) + { + OSL_ASSERT( !pOEntry->aInterfaces.empty() && + pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 ); + + sal_Int32 index = pOEntry->find( pInterface, 1 ); + OSL_ASSERT( index > 0 ); + if (index > 0) + { + InterfaceEntry & entry = pOEntry->aInterfaces[ index ]; + OSL_ASSERT( entry.pInterface == pInterface ); + if (entry.fpFreeProxy != 0) + { + --entry.refCount; + if (entry.refCount == 0) + { + uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy; + typelib_TypeDescription * pTypeDescr = + reinterpret_cast< typelib_TypeDescription * >( + entry.pTypeDescr ); + + pOEntry->aInterfaces.erase( + pOEntry->aInterfaces.begin() + index ); + if (pOEntry->find( pInterface, index ) < 0) + { + // proxy ptr not registered for another interface: + // remove from ptr map +#if OSL_DEBUG_LEVEL > 0 + ::std::size_t erased = +#endif + that->aPtr2ObjectMap.erase( pInterface ); + OSL_ASSERT( erased == 1 ); + } + + guard.clear(); + + typelib_typedescription_release( pTypeDescr ); + (*fpFreeProxy)( pEnv, pInterface ); + } + } + } + } +} + +static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface) +{ + uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface); +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_getObjectIdentifier( + uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) +{ + OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); + if (*ppOId) + { + ::rtl_uString_release( *ppOId ); + *ppOId = 0; + } + + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::ClearableMutexGuard guard( that->mutex ); + + Ptr2ObjectMap::const_iterator const iFind( + that->aPtr2ObjectMap.find( pInterface ) ); + if (iFind == that->aPtr2ObjectMap.end()) + { + guard.clear(); + (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface ); + } + else + { + rtl_uString * hstr = iFind->second->oid.pData; + rtl_uString_acquire( hstr ); + *ppOId = hstr; + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_getRegisteredInterface( + uno_ExtEnvironment * pEnv, void ** ppInterface, + rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) +{ + OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); + if (*ppInterface) + { + (*pEnv->releaseInterface)( pEnv, *ppInterface ); + *ppInterface = 0; + } + + OUString const & rOId = OUString::unacquired( &pOId ); + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::MutexGuard guard( that->mutex ); + + OId2ObjectMap::const_iterator const iFind + ( that->aOId2ObjectMap.find( rOId ) ); + if (iFind != that->aOId2ObjectMap.end()) + { + InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr ); + if (pIEntry) + { + (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface ); + *ppInterface = pIEntry->pInterface; + } + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_getRegisteredInterfaces( + uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen, + uno_memAlloc memAlloc ) +{ + OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" ); + uno_DefaultEnvironment * that = + static_cast< uno_DefaultEnvironment * >( pEnv ); + ::osl::MutexGuard guard( that->mutex ); + + sal_Int32 nLen = that->aPtr2ObjectMap.size(); + sal_Int32 nPos = 0; + void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) ); + + Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() ); + Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() ); + while (iPos != iEnd) + { + (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first ); + ++iPos; + } + + *pppInterfaces = ppInterfaces; + *pnLen = nLen; +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_acquire( uno_Environment * pEnv ) +{ + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + ::osl_incrementInterlockedCount( &that->nWeakRef ); + ::osl_incrementInterlockedCount( &that->nRef ); +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_release( uno_Environment * pEnv ) +{ + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + if (! ::osl_decrementInterlockedCount( &that->nRef )) + { + // invoke dispose callback + if (pEnv->environmentDisposing) + { + (*pEnv->environmentDisposing)( pEnv ); + } + + OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" ); + } + // free memory if no weak refs left + if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) + { + delete that; + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv ) +{ + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + ::osl_incrementInterlockedCount( &that->nWeakRef ); +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv ) +{ + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) + { + delete that; + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_harden( + uno_Environment ** ppHardEnv, uno_Environment * pEnv ) +{ + if (*ppHardEnv) + { + (*(*ppHardEnv)->release)( *ppHardEnv ); + *ppHardEnv = 0; + } + + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + { + ::osl::MutexGuard guard( theEnvironmentsData::get().mutex ); + if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead + { + that->nRef = 0; + return; + } + } + ::osl_incrementInterlockedCount( &that->nWeakRef ); + *ppHardEnv = pEnv; +} + +//------------------------------------------------------------------------------ +static void SAL_CALL defenv_dispose( uno_Environment * ) +{ +} +} + +//______________________________________________________________________________ +uno_DefaultEnvironment::uno_DefaultEnvironment( + const OUString & rEnvDcp_, void * pContext_ ) + : nRef( 0 ), + nWeakRef( 0 ) +{ + uno_Environment * that = reinterpret_cast< uno_Environment * >(this); + that->pReserved = 0; + // functions + that->acquire = defenv_acquire; + that->release = defenv_release; + that->acquireWeak = defenv_acquireWeak; + that->releaseWeak = defenv_releaseWeak; + that->harden = defenv_harden; + that->dispose = defenv_dispose; + that->pExtEnv = this; + // identifier + ::rtl_uString_acquire( rEnvDcp_.pData ); + that->pTypeName = rEnvDcp_.pData; + that->pContext = pContext_; + + // will be late initialized + that->environmentDisposing = 0; + + uno_ExtEnvironment::registerInterface = defenv_registerInterface; + uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface; + uno_ExtEnvironment::revokeInterface = defenv_revokeInterface; + uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier; + uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface; + uno_ExtEnvironment::getRegisteredInterfaces = + defenv_getRegisteredInterfaces; + +} + +//______________________________________________________________________________ +uno_DefaultEnvironment::~uno_DefaultEnvironment() +{ + ::rtl_uString_release( ((uno_Environment *) this)->pTypeName ); +} + +//============================================================================== +static void writeLine( + void * stream, const sal_Char * pLine, const sal_Char * pFilter ) +{ + if (pFilter && *pFilter) + { + // lookup pFilter in pLine + while (*pLine) + { + if (*pLine == *pFilter) + { + sal_Int32 nPos = 1; + while (pLine[nPos] && pFilter[nPos] == pLine[nPos]) + { + ++nPos; + } + if (! pFilter[nPos]) + { + if (stream) + { + fprintf( (FILE *) stream, "%s\n", pLine ); + } + else + { + OSL_TRACE( pLine ); + OSL_TRACE( "\n" ); + } + } + } + ++pLine; + } + } + else + { + if (stream) + { + fprintf( (FILE *) stream, "%s\n", pLine ); + } + else + { + fprintf( stderr, "%s\n", pLine ); + } + } +} + +//============================================================================== +static void writeLine( + void * stream, const OUString & rLine, const sal_Char * pFilter ) +{ + ::rtl::OString aLine( ::rtl::OUStringToOString( + rLine, RTL_TEXTENCODING_ASCII_US ) ); + writeLine( stream, aLine.getStr(), pFilter ); +} + +//############################################################################## +extern "C" void SAL_CALL uno_dumpEnvironment( + void * stream, uno_Environment * pEnv, const sal_Char * pFilter ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( pEnv, "### null ptr!" ); + ::rtl::OUStringBuffer buf; + + if (! pEnv->pExtEnv) + { + writeLine( stream, "###################################" + "###########################################", pFilter ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") ); + buf.append( pEnv->pTypeName ); + writeLine( stream, buf.makeStringAndClear(), pFilter ); + writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter ); + return; + } + + writeLine( stream, "########################################" + "######################################", pFilter ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") ); + buf.append( pEnv->pTypeName ); + writeLine( stream, buf.makeStringAndClear(), pFilter ); + + uno_DefaultEnvironment * that = + reinterpret_cast< uno_DefaultEnvironment * >(pEnv); + ::osl::MutexGuard guard( that->mutex ); + + Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap ); + OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() ); + while (iPos != that->aOId2ObjectMap.end()) + { + ObjectEntry * pOEntry = iPos->second; + + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") ); + if (pOEntry->mixedObject) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") ); + buf.append( pOEntry->nRef, 10 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") ); + buf.append( pOEntry->oid ); + buf.append( (sal_Unicode) '\"' ); + writeLine( stream, buf.makeStringAndClear(), pFilter ); + + for ( ::std::size_t nPos = 0; + nPos < pOEntry->aInterfaces.size(); ++nPos ) + { + const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos]; + + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") ); + buf.append( + ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName ); + if (rIEntry.fpFreeProxy) + { + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") ); + buf.append( + reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 ); + } + else + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") ); + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") ); + buf.append( + reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 ); + + if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0) + { + ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface ); + if (erased != 1) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + " (ptr not found in map!)") ); + } + } + writeLine( stream, buf.makeStringAndClear(), pFilter ); + } + ++iPos; + } + if (! ptr2obj.empty()) + writeLine( stream, "ptr map inconsistency!!!", pFilter ); + writeLine( stream, "#####################################" + "#########################################", pFilter ); +} + +//############################################################################## +extern "C" void SAL_CALL uno_dumpEnvironmentByName( + void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter ) + SAL_THROW_EXTERN_C() +{ + uno_Environment * pEnv = 0; + uno_getEnvironment( &pEnv, pEnvDcp, 0 ); + if (pEnv) + { + ::uno_dumpEnvironment( stream, pEnv, pFilter ); + (*pEnv->release)( pEnv ); + } + else + { + ::rtl::OUStringBuffer buf( 32 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") ); + buf.append( pEnvDcp ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") ); + writeLine( stream, buf.makeStringAndClear(), pFilter ); + } +} + +//------------------------------------------------------------------------------ +inline static const OUString & unoenv_getStaticOIdPart() +{ + static OUString * s_pStaticOidPart = 0; + if (! s_pStaticOidPart) + { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + if (! s_pStaticOidPart) + { + ::rtl::OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); + // pid + oslProcessInfo info; + info.Size = sizeof(oslProcessInfo); + if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) == + osl_Process_E_None) + { + aRet.append( (sal_Int64)info.Ident, 16 ); + } + else + { + aRet.appendAscii( + RTL_CONSTASCII_STRINGPARAM("unknown process id") ); + } + // good guid + sal_uInt8 ar[16]; + ::rtl_getGlobalProcessId( ar ); + aRet.append( (sal_Unicode)';' ); + for ( sal_Int32 i = 0; i < 16; ++i ) + aRet.append( (sal_Int32)ar[i], 16 ); + + static OUString s_aStaticOidPart( aRet.makeStringAndClear() ); + s_pStaticOidPart = &s_aStaticOidPart; + } + } + return *s_pStaticOidPart; +} + +extern "C" +{ + +//------------------------------------------------------------------------------ +static void SAL_CALL unoenv_computeObjectIdentifier( + uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) +{ + OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); + if (*ppOId) + { + ::rtl_uString_release( *ppOId ); + *ppOId = 0; + } + + uno_Interface * pUnoI = (uno_Interface *) + ::cppu::binuno_queryInterface( + pInterface, *typelib_static_type_getByTypeClass( + typelib_TypeClass_INTERFACE ) ); + if (0 != pUnoI) + { + (*pUnoI->release)( pUnoI ); + // interface + ::rtl::OUStringBuffer oid( 64 ); + oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 ); + oid.append( static_cast< sal_Unicode >(';') ); + // environment[context] + oid.append( ((uno_Environment *) pEnv)->pTypeName ); + oid.append( static_cast< sal_Unicode >('[') ); + oid.append( reinterpret_cast< sal_Int64 >( + reinterpret_cast< + uno_Environment * >(pEnv)->pContext ), 16 ); + // process;good guid + oid.append( unoenv_getStaticOIdPart() ); + OUString aStr( oid.makeStringAndClear() ); + ::rtl_uString_acquire( *ppOId = aStr.pData ); + } +} + +//============================================================================== +static void SAL_CALL unoenv_acquireInterface( + uno_ExtEnvironment *, void * pUnoI_ ) +{ + uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); + (*pUnoI->acquire)( pUnoI ); +} + +//============================================================================== +static void SAL_CALL unoenv_releaseInterface( + uno_ExtEnvironment *, void * pUnoI_ ) +{ + uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); + (*pUnoI->release)( pUnoI ); +} +} + +//______________________________________________________________________________ +EnvironmentsData::~EnvironmentsData() +{ + ::osl::MutexGuard guard( mutex ); + + for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); + iPos != aName2EnvMap.end(); ++iPos ) + { + uno_Environment * pWeak = iPos->second; + uno_Environment * pHard = 0; + (*pWeak->harden)( &pHard, pWeak ); + (*pWeak->releaseWeak)( pWeak ); + + if (pHard) + { +#if OSL_DEBUG_LEVEL > 1 + ::uno_dumpEnvironment( 0, pHard, 0 ); +#endif +#if defined CPPU_LEAK_STATIC_DATA + pHard->environmentDisposing = 0; // set to null => wont be called +#else + (*pHard->dispose)( pHard ); // send explicit dispose +#endif + (*pHard->release)( pHard ); + } + } +} + +//______________________________________________________________________________ +inline void EnvironmentsData::getEnvironment( + uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ) +{ + if (*ppEnv) + { + (*(*ppEnv)->release)( *ppEnv ); + *ppEnv = 0; + } + + OUString aKey( + OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) ); + aKey += rEnvDcp; + + // try to find registered mapping + OUString2EnvironmentMap::const_iterator const iFind( + aName2EnvMap.find( aKey ) ); + if (iFind != aName2EnvMap.end()) + { + uno_Environment * pWeak = iFind->second; + (*pWeak->harden)( ppEnv, pWeak ); + } +} + +//______________________________________________________________________________ +inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv ) +{ + OSL_ENSURE( ppEnv, "### null ptr!" ); + uno_Environment * pEnv = *ppEnv; + + OUString aKey( + OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) ); + aKey += pEnv->pTypeName; + + // try to find registered environment + OUString2EnvironmentMap::const_iterator const iFind( + aName2EnvMap.find( aKey ) ); + if (iFind == aName2EnvMap.end()) + { + (*pEnv->acquireWeak)( pEnv ); + ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion( + aName2EnvMap.insert( + OUString2EnvironmentMap::value_type( aKey, pEnv ) ) ); + OSL_ENSURE( + insertion.second, "### insertion of env into map failed?!" ); + } + else + { + uno_Environment * pHard = 0; + uno_Environment * pWeak = iFind->second; + (*pWeak->harden)( &pHard, pWeak ); + if (pHard) + { + if (pEnv) + (*pEnv->release)( pEnv ); + *ppEnv = pHard; + } + else // registered one is dead + { + (*pWeak->releaseWeak)( pWeak ); + (*pEnv->acquireWeak)( pEnv ); + aName2EnvMap[ aKey ] = pEnv; + } + } +} + +//______________________________________________________________________________ +inline void EnvironmentsData::getRegisteredEnvironments( + uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, + const OUString & rEnvDcp ) +{ + OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" ); + + // max size + uno_Environment ** ppFound = (uno_Environment **)alloca( + sizeof(uno_Environment *) * aName2EnvMap.size() ); + sal_Int32 nSize = 0; + + // find matching environment + for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); + iPos != aName2EnvMap.end(); ++iPos ) + { + uno_Environment * pWeak = iPos->second; + if (!rEnvDcp.getLength() || + rEnvDcp.equals( pWeak->pTypeName )) + { + ppFound[nSize] = 0; + (*pWeak->harden)( &ppFound[nSize], pWeak ); + if (ppFound[nSize]) + ++nSize; + } + } + + *pnLen = nSize; + if (nSize) + { + *pppEnvs = (uno_Environment **) (*memAlloc)( + sizeof (uno_Environment *) * nSize ); + OSL_ASSERT( *pppEnvs ); + while (nSize--) + { + (*pppEnvs)[nSize] = ppFound[nSize]; + } + } + else + { + *pppEnvs = 0; + } +} + +static bool loadEnv(OUString const & cLibStem, + uno_Environment * pEnv, + void * /*pContext*/) +{ + // late init with some code from matching uno language binding + // will be unloaded by environment + oslModule hMod = cppu::detail::loadModule( cLibStem ); + + if (!hMod) + return false; + + OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT)); + uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc) + ::osl_getFunctionSymbol( hMod, aSymbolName.pData ); + if (!fpInit) + { + ::osl_unloadModule( hMod ); + return false; + } + + (*fpInit)( pEnv ); // init of environment + ::rtl_registerModuleForUnloading( hMod ); + + return true; +} + + +extern "C" +{ + +//------------------------------------------------------------------------------ +static uno_Environment * initDefaultEnvironment( + const OUString & rEnvDcp, void * pContext ) +{ + uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase; + (*pEnv->acquire)( pEnv ); + + OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp); + + // create default environment + if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) + { + uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; + that->computeObjectIdentifier = unoenv_computeObjectIdentifier; + that->acquireInterface = unoenv_acquireInterface; + that->releaseInterface = unoenv_releaseInterface; + + OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp); + if (envPurpose.getLength()) + { + rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1); + libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") ); + + if(!loadEnv(libStem, pEnv, pContext)) + { + pEnv->release(pEnv); + return NULL; + } + } + } + else + { + // late init with some code from matching uno language binding + ::rtl::OUStringBuffer aLibName( 16 ); + aLibName.append( envTypeName ); + aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) ); + OUString aStr( aLibName.makeStringAndClear() ); + + if (!loadEnv(aStr, pEnv, pContext)) + { + pEnv->release(pEnv); + return NULL; + } + } + + return pEnv; +} + +//############################################################################## +void SAL_CALL uno_createEnvironment( + uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppEnv, "### null ptr!" ); + if (*ppEnv) + (*(*ppEnv)->release)( *ppEnv ); + + OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); + *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); +} + +//############################################################################## +void SAL_CALL uno_direct_getEnvironment( + uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppEnv, "### null ptr!" ); + OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); + + EnvironmentsData & rData = theEnvironmentsData::get(); + + ::osl::MutexGuard guard( rData.mutex ); + rData.getEnvironment( ppEnv, rEnvDcp, pContext ); + if (! *ppEnv) + { + *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); + if (*ppEnv) + { + // register new environment: + rData.registerEnvironment( ppEnv ); + } + } +} + +//############################################################################## +void SAL_CALL uno_getRegisteredEnvironments( + uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, + rtl_uString * pEnvDcp ) + SAL_THROW_EXTERN_C() +{ + EnvironmentsData & rData = theEnvironmentsData::get(); + + ::osl::MutexGuard guard( rData.mutex ); + rData.getRegisteredEnvironments( + pppEnvs, pnLen, memAlloc, + (pEnvDcp ? OUString(pEnvDcp) : OUString()) ); +} + +} // extern "C" + +} + diff --git a/cppu/source/uno/lbmap.cxx b/cppu/source/uno/lbmap.cxx new file mode 100644 index 000000000000..d2c4a6f60641 --- /dev/null +++ b/cppu/source/uno/lbmap.cxx @@ -0,0 +1,692 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" + +#include "IdentityMapping.hxx" + +#include <hash_map> +#include <set> +#include <algorithm> + +#include "rtl/unload.h" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "osl/module.h" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "osl/interlck.h" + +#include "uno/dispatcher.h" +#include "uno/mapping.h" +#include "uno/lbnames.h" +#include "uno/environment.hxx" + +#include "typelib/typedescription.h" + +#include "cppu/EnvDcp.hxx" +#include "cascade_mapping.hxx" +#include "IdentityMapping.hxx" +#include "loadmodule.hxx" + +using namespace std; +using namespace osl; +using namespace rtl; +using namespace com::sun::star::uno; + + +namespace cppu +{ + +class Mapping +{ + uno_Mapping * _pMapping; + +public: + inline Mapping( uno_Mapping * pMapping = 0 ) SAL_THROW( () ); + inline Mapping( const Mapping & rMapping ) SAL_THROW( () ); + inline ~Mapping() SAL_THROW( () ); + inline Mapping & SAL_CALL operator = ( uno_Mapping * pMapping ) SAL_THROW( () ); + inline Mapping & SAL_CALL operator = ( const Mapping & rMapping ) SAL_THROW( () ) + { return operator = ( rMapping._pMapping ); } + inline uno_Mapping * SAL_CALL get() const SAL_THROW( () ) + { return _pMapping; } + inline sal_Bool SAL_CALL is() const SAL_THROW( () ) + { return (_pMapping != 0); } +}; +//__________________________________________________________________________________________________ +inline Mapping::Mapping( uno_Mapping * pMapping ) SAL_THROW( () ) + : _pMapping( pMapping ) +{ + if (_pMapping) + (*_pMapping->acquire)( _pMapping ); +} +//__________________________________________________________________________________________________ +inline Mapping::Mapping( const Mapping & rMapping ) SAL_THROW( () ) + : _pMapping( rMapping._pMapping ) +{ + if (_pMapping) + (*_pMapping->acquire)( _pMapping ); +} +//__________________________________________________________________________________________________ +inline Mapping::~Mapping() SAL_THROW( () ) +{ + if (_pMapping) + (*_pMapping->release)( _pMapping ); +} +//__________________________________________________________________________________________________ +inline Mapping & Mapping::operator = ( uno_Mapping * pMapping ) SAL_THROW( () ) +{ + if (pMapping) + (*pMapping->acquire)( pMapping ); + if (_pMapping) + (*_pMapping->release)( _pMapping ); + _pMapping = pMapping; + return *this; +} + +//================================================================================================== +struct MappingEntry +{ + sal_Int32 nRef; + uno_Mapping * pMapping; + uno_freeMappingFunc freeMapping; + OUString aMappingName; + + MappingEntry( + uno_Mapping * pMapping_, uno_freeMappingFunc freeMapping_, + const OUString & rMappingName_ ) + SAL_THROW( () ) + : nRef( 1 ) + , pMapping( pMapping_ ) + , freeMapping( freeMapping_ ) + , aMappingName( rMappingName_ ) + {} +}; +//-------------------------------------------------------------------------------------------------- +struct FctOUStringHash : public unary_function< const OUString &, size_t > +{ + size_t operator()( const OUString & rKey ) const SAL_THROW( () ) + { return (size_t)rKey.hashCode(); } +}; +//-------------------------------------------------------------------------------------------------- +struct FctPtrHash : public unary_function< uno_Mapping *, size_t > +{ + size_t operator()( uno_Mapping * pKey ) const SAL_THROW( () ) + { return (size_t)pKey; } +}; + +typedef hash_map< + OUString, MappingEntry *, FctOUStringHash, equal_to< OUString > > t_OUString2Entry; +typedef hash_map< + uno_Mapping *, MappingEntry *, FctPtrHash, equal_to< uno_Mapping * > > t_Mapping2Entry; + +typedef set< uno_getMappingFunc > t_CallbackSet; +typedef set< OUString > t_OUStringSet; + +//================================================================================================== +struct MappingsData +{ + Mutex aMappingsMutex; + t_OUString2Entry aName2Entry; + t_Mapping2Entry aMapping2Entry; + + Mutex aCallbacksMutex; + t_CallbackSet aCallbacks; + + Mutex aNegativeLibsMutex; + t_OUStringSet aNegativeLibs; +}; +//-------------------------------------------------------------------------------------------------- +static MappingsData & getMappingsData() SAL_THROW( () ) +{ + static MappingsData * s_p = 0; + if (! s_p) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_p) + { + //TODO This memory is leaked; see #i63473# for when this should be + // changed again: + s_p = new MappingsData; + } + } + return *s_p; +} + +/** + * This class mediates two different mapping via uno, e.g. form any language to uno, + * then from uno to any other language. + */ +struct uno_Mediate_Mapping : public uno_Mapping +{ + sal_Int32 nRef; + + Environment aFrom; + Environment aTo; + + Mapping aFrom2Uno; + Mapping aUno2To; + + OUString aAddPurpose; + + uno_Mediate_Mapping( + const Environment & rFrom_, const Environment & rTo_, + const Mapping & rFrom2Uno_, const Mapping & rUno2To_, + const OUString & rAddPurpose ) + SAL_THROW( () ); +}; +extern "C" +{ +//-------------------------------------------------------------------------------------------------- +static void SAL_CALL mediate_free( uno_Mapping * pMapping ) + SAL_THROW( () ) +{ + delete static_cast< uno_Mediate_Mapping * >( pMapping ); +} +//-------------------------------------------------------------------------------------------------- +static void SAL_CALL mediate_acquire( uno_Mapping * pMapping ) + SAL_THROW( () ) +{ + if (1 == ::osl_incrementInterlockedCount( + & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef )) + { + uno_registerMapping( + &pMapping, mediate_free, + static_cast< uno_Mediate_Mapping * >( pMapping )->aFrom.get(), + static_cast< uno_Mediate_Mapping * >( pMapping )->aTo.get(), + static_cast< uno_Mediate_Mapping * >( pMapping )->aAddPurpose.pData ); + } +} +//-------------------------------------------------------------------------------------------------- +static void SAL_CALL mediate_release( uno_Mapping * pMapping ) + SAL_THROW( () ) +{ + if (! ::osl_decrementInterlockedCount( + & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef )) + { + uno_revokeMapping( pMapping ); + } +} +//-------------------------------------------------------------------------------------------------- +static void SAL_CALL mediate_mapInterface( + uno_Mapping * pMapping, + void ** ppOut, void * pInterface, + typelib_InterfaceTypeDescription * pInterfaceTypeDescr ) + SAL_THROW( () ) +{ + OSL_ENSURE( pMapping && ppOut, "### null ptr!" ); + if (pMapping && ppOut) + { + uno_Mediate_Mapping * that = static_cast< uno_Mediate_Mapping * >( pMapping ); + uno_Mapping * pFrom2Uno = that->aFrom2Uno.get(); + + uno_Interface * pUnoI = 0; + (*pFrom2Uno->mapInterface)( pFrom2Uno, (void **) &pUnoI, pInterface, pInterfaceTypeDescr ); + if (0 == pUnoI) + { + void * pOut = *ppOut; + if (0 != pOut) + { + uno_ExtEnvironment * pTo = that->aTo.get()->pExtEnv; + OSL_ENSURE( 0 != pTo, "### cannot release out interface: leaking!" ); + if (0 != pTo) + (*pTo->releaseInterface)( pTo, pOut ); + *ppOut = 0; // set to 0 anyway, because mapping was not successfull! + } + } + else + { + uno_Mapping * pUno2To = that->aUno2To.get(); + (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr ); + (*pUnoI->release)( pUnoI ); + } + } +} +} +//__________________________________________________________________________________________________ +uno_Mediate_Mapping::uno_Mediate_Mapping( + const Environment & rFrom_, const Environment & rTo_, + const Mapping & rFrom2Uno_, const Mapping & rUno2To_, + const OUString & rAddPurpose_ ) + SAL_THROW( () ) + : nRef( 1 ) + , aFrom( rFrom_ ) + , aTo( rTo_ ) + , aFrom2Uno( rFrom2Uno_ ) + , aUno2To( rUno2To_ ) + , aAddPurpose( rAddPurpose_ ) +{ + uno_Mapping::acquire = mediate_acquire; + uno_Mapping::release = mediate_release; + uno_Mapping::mapInterface = mediate_mapInterface; +} + +//================================================================================================== +static inline OUString getMappingName( + const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) + SAL_THROW( () ) +{ + OUStringBuffer aKey( 64 ); + aKey.append( rAddPurpose ); + aKey.append( (sal_Unicode)';' ); + aKey.append( rFrom.getTypeName() ); + aKey.append( (sal_Unicode)'[' ); + aKey.append( reinterpret_cast< sal_IntPtr >(rFrom.get()), 16 ); + aKey.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); + aKey.append( rTo.getTypeName() ); + aKey.append( (sal_Unicode)'[' ); + aKey.append( reinterpret_cast< sal_IntPtr >(rTo.get()), 16 ); + aKey.append( (sal_Unicode)']' ); + return aKey.makeStringAndClear(); +} +//================================================================================================== +static inline OUString getBridgeName( + const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) + SAL_THROW( () ) +{ + OUStringBuffer aBridgeName( 16 ); + if (rAddPurpose.getLength()) + { + aBridgeName.append( rAddPurpose ); + aBridgeName.append( (sal_Unicode)'_' ); + } + aBridgeName.append( EnvDcp::getTypeName(rFrom.getTypeName()) ); + aBridgeName.append( (sal_Unicode)'_' ); + aBridgeName.append( EnvDcp::getTypeName(rTo.getTypeName()) ); + return aBridgeName.makeStringAndClear(); +} +//================================================================================================== +static inline void setNegativeBridge( const OUString & rBridgeName ) + SAL_THROW( () ) +{ + MappingsData & rData = getMappingsData(); + MutexGuard aGuard( rData.aNegativeLibsMutex ); + rData.aNegativeLibs.insert( rBridgeName ); +} +//================================================================================================== +static inline oslModule loadModule( const OUString & rBridgeName ) + SAL_THROW( () ) +{ + sal_Bool bNeg; + { + MappingsData & rData = getMappingsData(); + MutexGuard aGuard( rData.aNegativeLibsMutex ); + const t_OUStringSet::const_iterator iFind( rData.aNegativeLibs.find( rBridgeName ) ); + bNeg = (iFind != rData.aNegativeLibs.end()); + } + + if (! bNeg) + { + oslModule hModule = cppu::detail::loadModule( rBridgeName ); + + if (hModule) + return hModule; + + setNegativeBridge( rBridgeName ); // no load again + } + return 0; +} +//================================================================================================== +static Mapping loadExternalMapping( + const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) + SAL_THROW( () ) +{ + OSL_ASSERT( rFrom.is() && rTo.is() ); + if (rFrom.is() && rTo.is()) + { + // find proper lib + oslModule hModule = 0; + OUString aName; + + if (EnvDcp::getTypeName(rFrom.getTypeName()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) + hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) ); + if (! hModule) + hModule = loadModule( aName = getBridgeName( rFrom, rTo, rAddPurpose ) ); + if (! hModule) + hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) ); + + if (hModule) + { + OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM(UNO_EXT_GETMAPPING) ); + uno_ext_getMappingFunc fpGetMapFunc = + (uno_ext_getMappingFunc)::osl_getFunctionSymbol( + hModule, aSymbolName.pData ); + + if (fpGetMapFunc) + { + Mapping aExt; + (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() ); + OSL_ASSERT( aExt.is() ); + if (aExt.is()) + { + ::rtl_registerModuleForUnloading( hModule ); + return aExt; + } + } + ::osl_unloadModule( hModule ); + setNegativeBridge( aName ); + } + } + return Mapping(); +} + +//================================================================================================== +static Mapping getDirectMapping( + const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose = OUString() ) + SAL_THROW( () ) +{ + OSL_ASSERT( rFrom.is() && rTo.is() ); + if (rFrom.is() && rTo.is()) + { + MappingsData & rData = getMappingsData(); + ClearableMutexGuard aGuard( rData.aMappingsMutex ); + + // try to find registered mapping + const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find( + getMappingName( rFrom, rTo, rAddPurpose ) ) ); + + if (iFind == rData.aName2Entry.end()) + { + aGuard.clear(); + return loadExternalMapping( rFrom, rTo, rAddPurpose ); + } + else + { + return Mapping( (*iFind).second->pMapping ); + } + } + return Mapping(); +} + +//-------------------------------------------------------------------------------------------------- +static inline Mapping createMediateMapping( + const Environment & rFrom, const Environment & rTo, + const Mapping & rFrom2Uno, const Mapping & rUno2To, + const OUString & rAddPurpose ) + SAL_THROW( () ) +{ + uno_Mapping * pRet = new uno_Mediate_Mapping( + rFrom, rTo, rFrom2Uno, rUno2To, rAddPurpose ); // ref count initially 1 + uno_registerMapping( + &pRet, mediate_free, rFrom.get(), rTo.get(), rAddPurpose.pData ); + Mapping aRet( pRet ); + (*pRet->release)( pRet ); + return aRet; +} +//================================================================================================== +static Mapping getMediateMapping( + const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) + SAL_THROW( () ) +{ + Environment aUno; + Mapping aUno2To; + + // backwards: from dest to source of mapping chain + + // connect to uno + OUString aUnoEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ); + if (rTo.getTypeName() == aUnoEnvTypeName) // to is uno + { + aUno = rTo; + // no Uno2To mapping necessary + } + else + { + // get registered uno env + ::uno_getEnvironment( (uno_Environment **)&aUno, aUnoEnvTypeName.pData, 0 ); + + aUno2To = getDirectMapping( aUno, rTo ); + // : uno <-> to + if (! aUno2To.is()) + return Mapping(); + } + + // connect to uno + if (rAddPurpose.getLength()) // insert purpose mapping between new ano_uno <-> uno + { + // create anonymous uno env + Environment aAnUno; + ::uno_createEnvironment( (uno_Environment **)&aAnUno, aUnoEnvTypeName.pData, 0 ); + + Mapping aAnUno2Uno( getDirectMapping( aAnUno, aUno, rAddPurpose ) ); + if (! aAnUno2Uno.is()) + return Mapping(); + + if (aUno2To.is()) // to is not uno + { + // create another purposed mediate mapping + aUno2To = createMediateMapping( aAnUno, rTo, aAnUno2Uno, aUno2To, rAddPurpose ); + // : ano_uno <-> uno <-> to + } + else + { + aUno2To = aAnUno2Uno; + // : ano_uno <-> to (i.e., uno) + } + aUno = aAnUno; + } + + Mapping aFrom2Uno( getDirectMapping( rFrom, aUno ) ); + if (aFrom2Uno.is() && aUno2To.is()) + { + return createMediateMapping( rFrom, rTo, aFrom2Uno, aUno2To, rAddPurpose ); + // : from <-> some uno ... + } + + return Mapping(); +} +} + +using namespace ::cppu; + +extern "C" +{ +//################################################################################################## +void SAL_CALL uno_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo, + rtl_uString * pAddPurpose ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" ); + if (*ppMapping) + { + (*(*ppMapping)->release)( *ppMapping ); + *ppMapping = 0; + } + + Mapping aRet; + Environment aFrom( pFrom ), aTo( pTo ); + + OUString aAddPurpose; + if (pAddPurpose) + aAddPurpose = pAddPurpose; + + MappingsData & rData = getMappingsData(); + + // try registered mapping + { + MutexGuard aGuard( rData.aMappingsMutex ); + const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find( + getMappingName( aFrom, aTo, aAddPurpose ) ) ); + if (iFind != rData.aName2Entry.end()) + aRet = (*iFind).second->pMapping; + } + + // See if an identity mapping does fit. + if (!aRet.is() && pFrom == pTo && !aAddPurpose.getLength()) + aRet = createIdentityMapping(pFrom); + + if (!aRet.is()) + { + getCascadeMapping(ppMapping, pFrom, pTo, pAddPurpose); + + if (*ppMapping) + return; + } + + if (! aRet.is()) // try callback chain + { + MutexGuard aGuard( rData.aCallbacksMutex ); + for ( t_CallbackSet::const_iterator iPos( rData.aCallbacks.begin() ); + iPos != rData.aCallbacks.end(); ++iPos ) + { + (**iPos)( ppMapping, pFrom, pTo, aAddPurpose.pData ); + if (*ppMapping) + return; + } + } + + if (! aRet.is()) + { + aRet = loadExternalMapping( aFrom, aTo, aAddPurpose ); // direct try + if (! aRet.is()) + aRet = getMediateMapping( aFrom, aTo, aAddPurpose ); // try via uno + } + + if (aRet.is()) + { + (*aRet.get()->acquire)( aRet.get() ); + *ppMapping = aRet.get(); + } +} +//################################################################################################## +void SAL_CALL uno_getMappingByName( + uno_Mapping ** ppMapping, rtl_uString * pFrom, rtl_uString * pTo, + rtl_uString * pAddPurpose ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" ); + if (*ppMapping) + { + (*(*ppMapping)->release)( *ppMapping ); + *ppMapping = 0; + } + + uno_Environment * pEFrom = 0; + uno_getEnvironment( &pEFrom, pFrom, 0 ); + OSL_ENSURE( pEFrom, "### cannot get source environment!" ); + if (pEFrom) + { + uno_Environment * pETo = 0; + uno_getEnvironment( &pETo, pTo, 0 ); + OSL_ENSURE( pETo, "### cannot get target environment!" ); + if (pETo) + { + ::uno_getMapping( ppMapping, pEFrom, pETo, pAddPurpose ); + (*pETo->release)( pETo ); + } + (*pEFrom->release)( pEFrom ); + } +} + +//################################################################################################## +void SAL_CALL uno_registerMapping( + uno_Mapping ** ppMapping, uno_freeMappingFunc freeMapping, + uno_Environment * pFrom, uno_Environment * pTo, rtl_uString * pAddPurpose ) + SAL_THROW_EXTERN_C() +{ + MappingsData & rData = getMappingsData(); + ClearableMutexGuard aGuard( rData.aMappingsMutex ); + + const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( *ppMapping ) ); + if (iFind == rData.aMapping2Entry.end()) + { + OUString aMappingName( + getMappingName( pFrom, pTo, pAddPurpose ? OUString(pAddPurpose) : OUString() ) ); +#if OSL_DEBUG_LEVEL > 1 + OString cstr( OUStringToOString( aMappingName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "> inserting new mapping: %s", cstr.getStr() ); +#endif + // count initially 1 + MappingEntry * pEntry = new MappingEntry( *ppMapping, freeMapping, aMappingName ); + rData.aName2Entry[ aMappingName ] = pEntry; + rData.aMapping2Entry[ *ppMapping ] = pEntry; + } + else + { + MappingEntry * pEntry = (*iFind).second; + ++pEntry->nRef; + + if (pEntry->pMapping != *ppMapping) // exchange mapping to be registered + { + (*pEntry->pMapping->acquire)( pEntry->pMapping ); + --pEntry->nRef; // correct count; kill mapping to be registered + aGuard.clear(); + (*freeMapping)( *ppMapping ); + *ppMapping = pEntry->pMapping; + } + } +} +//################################################################################################## +void SAL_CALL uno_revokeMapping( + uno_Mapping * pMapping ) + SAL_THROW_EXTERN_C() +{ + MappingsData & rData = getMappingsData(); + ClearableMutexGuard aGuard( rData.aMappingsMutex ); + + const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( pMapping ) ); + OSL_ASSERT( iFind != rData.aMapping2Entry.end() ); + MappingEntry * pEntry = (*iFind).second; + if (! --pEntry->nRef) + { + rData.aMapping2Entry.erase( pEntry->pMapping ); + rData.aName2Entry.erase( pEntry->aMappingName ); + aGuard.clear(); +#if OSL_DEBUG_LEVEL > 1 + OString cstr( OUStringToOString( pEntry->aMappingName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "> revoking mapping %s", cstr.getStr() ); +#endif + (*pEntry->freeMapping)( pEntry->pMapping ); + delete pEntry; + } +} + +//################################################################################################## +void SAL_CALL uno_registerMappingCallback( + uno_getMappingFunc pCallback ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( pCallback, "### null ptr!" ); + MappingsData & rData = getMappingsData(); + MutexGuard aGuard( rData.aCallbacksMutex ); + rData.aCallbacks.insert( pCallback ); +} +//################################################################################################## +void SAL_CALL uno_revokeMappingCallback( + uno_getMappingFunc pCallback ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( pCallback, "### null ptr!" ); + MappingsData & rData = getMappingsData(); + MutexGuard aGuard( rData.aCallbacksMutex ); + rData.aCallbacks.erase( pCallback ); +} +} // extern "C" + diff --git a/cppu/source/uno/loadmodule.cxx b/cppu/source/uno/loadmodule.cxx new file mode 100644 index 000000000000..e6858d247f04 --- /dev/null +++ b/cppu/source/uno/loadmodule.cxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" + +#include "sal/config.h" + +#include "osl/module.h" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" + +#include "loadmodule.hxx" + +namespace cppu { namespace detail { + +::oslModule loadModule(rtl::OUString const & name) { + rtl::OUStringBuffer b; +#if defined SAL_DLLPREFIX + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(SAL_DLLPREFIX)); +#endif + b.append(name); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION)); + return ::osl_loadModuleRelative( + reinterpret_cast< oslGenericFunction >(&loadModule), + b.makeStringAndClear().pData, + SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY); +} + +} } diff --git a/cppu/source/uno/loadmodule.hxx b/cppu/source/uno/loadmodule.hxx new file mode 100644 index 000000000000..77a9bb8d6dc0 --- /dev/null +++ b/cppu/source/uno/loadmodule.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_CPPU_SOURCE_UNO_CREATEMODULENAME_HXX +#define INCLUDED_CPPU_SOURCE_UNO_CREATEMODULENAME_HXX + +#include "sal/config.h" +#include "osl/module.h" + +namespace rtl { class OUString; } + +namespace cppu { namespace detail { + +/** Load a module. + + @param name + the nucleus of a module name (without any "lib...so", ".dll", etc. + decoration, and without a path). + + @return + the handle returned by osl_loadModule. +*/ +::oslModule loadModule(::rtl::OUString const & name); + +} } + +#endif diff --git a/cppu/source/uno/makefile.mk b/cppu/source/uno/makefile.mk new file mode 100644 index 000000000000..63bf4f0387ac --- /dev/null +++ b/cppu/source/uno/makefile.mk @@ -0,0 +1,55 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=cppu +TARGET=cppu_uno + +# --- Settings ----------------------------------------------------- + +.INCLUDE : ..$/..$/util$/makefile.pmk +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/data.obj \ + $(SLO)$/sequence.obj \ + $(SLO)$/any.obj \ + $(SLO)$/lbmap.obj \ + $(SLO)$/lbenv.obj \ + $(SLO)$/IdentityMapping.obj \ + $(SLO)$/EnvDcp.obj \ + $(SLO)$/cascade_mapping.obj \ + $(SLO)$/EnvStack.obj \ + $(SLO)$/env_subst.obj \ + $(SLO)$/loadmodule.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : ..$/..$/util$/target.pmk +.INCLUDE : target.mk diff --git a/cppu/source/uno/prim.hxx b/cppu/source/uno/prim.hxx new file mode 100644 index 000000000000..4acafd125d55 --- /dev/null +++ b/cppu/source/uno/prim.hxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef PRIM_HXX +#define PRIM_HXX + +#include "typelib/typedescription.h" +#ifndef _typelib_TypeClass_H_ +#include "typelib/typeclass.h" +#endif +#include "uno/sequence2.h" +#include "uno/any2.h" +#include "uno/data.h" +#include "uno/mapping.h" +#include "uno/dispatcher.h" + +#ifndef _OSL_INTERLCK_H +#include "osl/interlck.h" +#endif +#include "osl/diagnose.h" +#ifndef _RTL_USTRING_HXX +#include "rtl/ustring.hxx" +#endif +#include "rtl/alloc.h" + +#if OSL_DEBUG_LEVEL > 1 +#include "rtl/ustrbuf.hxx" +#include "rtl/string.hxx" +#endif + + +namespace cppu +{ + +extern uno_Sequence g_emptySeq; +extern typelib_TypeDescriptionReference * g_pVoidType; + +//-------------------------------------------------------------------------------------------------- +inline void * _map( + void * p, + typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, + uno_Mapping * mapping ) + SAL_THROW( () ) +{ + void * pRet = 0; + if (p) + { + if (pTypeDescr) + { + (*mapping->mapInterface)( + mapping, &pRet, p, (typelib_InterfaceTypeDescription *)pTypeDescr ); + } + else + { + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + (*mapping->mapInterface)( + mapping, &pRet, p, (typelib_InterfaceTypeDescription *)pTypeDescr ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + } + return pRet; +} +//-------------------------------------------------------------------------------------------------- +inline void _acquire( void * p, uno_AcquireFunc acquire ) SAL_THROW( () ) +{ + if (p) + { + if (acquire) + { + (*acquire)( p ); + } + else + { + (*((uno_Interface *)p)->acquire)( (uno_Interface *)p ); + } + } +} +//-------------------------------------------------------------------------------------------------- +inline void _release( void * p, uno_ReleaseFunc release ) SAL_THROW( () ) +{ + if (p) + { + if (release) + { + (*release)( p ); + } + else + { + (*((uno_Interface *)p)->release)( (uno_Interface *)p ); + } + } +} + +//------------------------------------------------------------------------------ +inline sal_uInt32 calcSeqMemSize( + sal_Int32 nElementSize, sal_Int32 nElements ) +{ + sal_uInt64 nSize = + (sal_uInt64) SAL_SEQUENCE_HEADER_SIZE + + ((sal_uInt64) nElementSize * (sal_uInt64) nElements); + if (nSize > 0xffffffffU) + return 0; + else + return (sal_uInt32) nSize; +} + +//-------------------------------------------------------------------------------------------------- +inline uno_Sequence * createEmptySequence() SAL_THROW( () ) +{ + ::osl_incrementInterlockedCount( &g_emptySeq.nRefCount ); + return &g_emptySeq; +} +//-------------------------------------------------------------------------------------------------- +inline typelib_TypeDescriptionReference * _getVoidType() + SAL_THROW( () ) +{ + if (! g_pVoidType) + { + g_pVoidType = * ::typelib_static_type_getByTypeClass( typelib_TypeClass_VOID ); + } + ::typelib_typedescriptionreference_acquire( g_pVoidType ); + return g_pVoidType; +} + +//-------------------------------------------------------------------------------------------------- +#if OSL_DEBUG_LEVEL > 0 +#define CONSTRUCT_EMPTY_ANY( pAny ) \ +(pAny)->pType = _getVoidType(); \ +(pAny)->pData = (void *)0xdeadbeef; +#else +#define CONSTRUCT_EMPTY_ANY( pAny ) \ +(pAny)->pType = _getVoidType(); \ +(pAny)->pData = (pAny); +#endif + +//-------------------------------------------------------------------------------------------------- +#define TYPE_ACQUIRE( pType ) \ + ::osl_incrementInterlockedCount( &(pType)->nRefCount ); + +//-------------------------------------------------------------------------------------------------- +extern "C" void * binuno_queryInterface( + void * pUnoI, typelib_TypeDescriptionReference * pDestType ); + +//-------------------------------------------------------------------------------------------------- +inline typelib_TypeDescriptionReference * _unionGetSetType( + void * pUnion, typelib_TypeDescription * pTD ) + SAL_THROW( () ) +{ + typelib_TypeDescriptionReference * pRet = 0; + sal_Int32 nPos; + + sal_Int64 * pDiscr = ((typelib_UnionTypeDescription *)pTD)->pDiscriminants; + sal_Int64 nDiscr = *(sal_Int64 *)pUnion; + for ( nPos = ((typelib_UnionTypeDescription *)pTD)->nMembers; nPos--; ) + { + if (pDiscr[nPos] == nDiscr) + { + pRet = ((typelib_UnionTypeDescription *)pTD)->ppTypeRefs[nPos]; + break; + } + } + if (nPos >= 0) + { + // default + pRet = ((typelib_UnionTypeDescription *)pTD)->pDefaultTypeRef; + } + typelib_typedescriptionreference_acquire( pRet ); + return pRet; +} +//-------------------------------------------------------------------------------------------------- +inline sal_Bool _type_equals( + typelib_TypeDescriptionReference * pType1, typelib_TypeDescriptionReference * pType2 ) + SAL_THROW( () ) +{ + return (pType1 == pType2 || + (pType1->eTypeClass == pType2->eTypeClass && + pType1->pTypeName->length == pType2->pTypeName->length && + ::rtl_ustr_compare( pType1->pTypeName->buffer, pType2->pTypeName->buffer ) == 0)); +} + +} + +#endif diff --git a/cppu/source/uno/sequence.cxx b/cppu/source/uno/sequence.cxx new file mode 100644 index 000000000000..933d38fc6b4f --- /dev/null +++ b/cppu/source/uno/sequence.cxx @@ -0,0 +1,1016 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_cppu.hxx" +#include <rtl/memory.h> +#include <rtl/alloc.h> +#include <osl/diagnose.h> +#include <osl/interlck.h> +#include <typelib/typedescription.h> +#include <uno/data.h> +#include <uno/dispatcher.h> +#include <uno/sequence2.h> + +#include "constr.hxx" +#include "copy.hxx" +#include "destr.hxx" + + +using namespace cppu; + +namespace cppu +{ + +//------------------------------------------------------------------------------ +static inline uno_Sequence * reallocSeq( + uno_Sequence * pReallocate, sal_Size nElementSize, sal_Int32 nElements ) +{ + OSL_ASSERT( nElements >= 0 ); + uno_Sequence * pNew = 0; + sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements ); + if (nSize > 0) + { + if (pReallocate == 0) + { + pNew = (uno_Sequence *) rtl_allocateMemory( nSize ); + } + else + { + pNew = (uno_Sequence *) rtl_reallocateMemory( pReallocate, nSize ); + } + if (pNew != 0) + { + // header init + pNew->nRefCount = 1; + pNew->nElements = nElements; + } + } + return pNew; +} + +//------------------------------------------------------------------------------ +static inline bool idefaultConstructElements( + uno_Sequence ** ppSeq, + typelib_TypeDescriptionReference * pElementType, + sal_Int32 nStartIndex, sal_Int32 nStopIndex, + sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements +{ + uno_Sequence * pSeq = *ppSeq; + switch (pElementType->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Unicode) * nStartIndex), + sizeof(sal_Unicode) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Bool) * nStartIndex), + sizeof(sal_Bool) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_BYTE: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Int8) * nStartIndex), + sizeof(sal_Int8) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Int16) * nStartIndex), + sizeof(sal_Int16) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Int32) * nStartIndex), + sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(sal_Int64) * nStartIndex), + sizeof(sal_Int64) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_FLOAT: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(float), nAlloc ); + if (pSeq != 0) + { + float * pElements = (float *) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = 0.0; + } + } + break; + } + case typelib_TypeClass_DOUBLE: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(double), nAlloc ); + if (pSeq != 0) + { + double * pElements = (double *) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = 0.0; + } + } + break; + } + case typelib_TypeClass_STRING: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc ); + if (pSeq != 0) + { + rtl_uString ** pElements = (rtl_uString **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = 0; + rtl_uString_new( &pElements[nPos] ); + } + } + break; + } + case typelib_TypeClass_TYPE: + { + if (nAlloc >= 0) + { + pSeq = reallocSeq( + pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc ); + } + if (pSeq != 0) + { + typelib_TypeDescriptionReference ** pElements = + (typelib_TypeDescriptionReference **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = _getVoidType(); + } + } + break; + } + case typelib_TypeClass_ANY: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc ); + if (pSeq != 0) + { + uno_Any * pElements = (uno_Any *) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + CONSTRUCT_EMPTY_ANY( &pElements[nPos] ); + } + } + break; + } + case typelib_TypeClass_ENUM: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); + if (pSeq != 0) + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 eEnum = + ((typelib_EnumTypeDescription *) + pElementTypeDescr)->nDefaultEnumValue; + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + + sal_Int32 * pElements = (sal_Int32 *) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = eEnum; + } + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); + if (pSeq != 0) + { + char * pElements = pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _defaultConstructStruct( + pElements + (nElementSize * nPos), + (typelib_CompoundTypeDescription *)pElementTypeDescr ); + } + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_ARRAY: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); + if (pSeq != 0) + { + char * pElements = pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _defaultConstructArray( + pElements + (nElementSize * nPos), + (typelib_ArrayTypeDescription *)pElementTypeDescr ); + } + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); + if (pSeq != 0) + { + sal_Int32 nValueOffset = + ((typelib_UnionTypeDescription *) + pElementTypeDescr)->nValueOffset; + sal_Int64 nDefaultDiscr = + ((typelib_UnionTypeDescription *) + pElementTypeDescr)->nDefaultDiscriminant; + + typelib_TypeDescription * pDefaultTypeDescr = 0; + TYPELIB_DANGER_GET( + &pDefaultTypeDescr, + ((typelib_UnionTypeDescription *) + pElementTypeDescr)->pDefaultTypeRef ); + + char * pElements = pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + char * pMem = pElements + (nElementSize * nPos); + ::uno_constructData( + (char *)pMem + nValueOffset, pDefaultTypeDescr ); + *(sal_Int64 *)pMem = nDefaultDiscr; + } + TYPELIB_DANGER_RELEASE( pDefaultTypeDescr ); + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_SEQUENCE: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc ); + if (pSeq != 0) + { + uno_Sequence ** pElements = + (uno_Sequence **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + pElements[nPos] = createEmptySequence(); + } + } + break; + } + case typelib_TypeClass_INTERFACE: // either C++ or C-UNO interface + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc ); + if (pSeq != 0) + { + ::rtl_zeroMemory( + pSeq->elements + (sizeof(void *) * nStartIndex), + sizeof(void *) * (nStopIndex - nStartIndex) ); + } + break; + default: + OSL_ENSURE( 0, "### unexpected element type!" ); + pSeq = 0; + break; + } + + if (pSeq == 0) + { + OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure + return false; + } + else + { + *ppSeq = pSeq; + return true; + } +} + +//------------------------------------------------------------------------------ +static inline bool icopyConstructFromElements( + uno_Sequence ** ppSeq, void * pSourceElements, + typelib_TypeDescriptionReference * pElementType, + sal_Int32 nStartIndex, sal_Int32 nStopIndex, + uno_AcquireFunc acquire, + sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements +{ + uno_Sequence * pSeq = *ppSeq; + switch (pElementType->eTypeClass) + { + case typelib_TypeClass_CHAR: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Unicode) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Unicode) * nStartIndex), + sizeof(sal_Unicode) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_BOOLEAN: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Bool) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Bool) * nStartIndex), + sizeof(sal_Bool) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_BYTE: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Int8) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Int8) * nStartIndex), + sizeof(sal_Int8) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Int16) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Int16) * nStartIndex), + sizeof(sal_Int16) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Int32) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex), + sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Int64) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Int64) * nStartIndex), + sizeof(sal_Int64) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_FLOAT: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(float), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(float) * nStartIndex), + (char *)pSourceElements + (sizeof(float) * nStartIndex), + sizeof(float) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_DOUBLE: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(double), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(double) * nStartIndex), + (char *)pSourceElements + (sizeof(double) * nStartIndex), + sizeof(double) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_ENUM: + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); + if (pSeq != 0) + { + ::rtl_copyMemory( + pSeq->elements + (sizeof(sal_Int32) * nStartIndex), + (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex), + sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); + } + break; + case typelib_TypeClass_STRING: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc ); + if (pSeq != 0) + { + rtl_uString ** pDestElements = (rtl_uString **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + ::rtl_uString_acquire( + ((rtl_uString **)pSourceElements)[nPos] ); + pDestElements[nPos] = ((rtl_uString **)pSourceElements)[nPos]; + } + } + break; + } + case typelib_TypeClass_TYPE: + { + if (nAlloc >= 0) + { + pSeq = reallocSeq( + pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc ); + } + if (pSeq != 0) + { + typelib_TypeDescriptionReference ** pDestElements = + (typelib_TypeDescriptionReference **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + TYPE_ACQUIRE( + ((typelib_TypeDescriptionReference **) + pSourceElements)[nPos] ); + pDestElements[nPos] = + ((typelib_TypeDescriptionReference **) + pSourceElements)[nPos]; + } + } + break; + } + case typelib_TypeClass_ANY: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc ); + if (pSeq != 0) + { + uno_Any * pDestElements = (uno_Any *) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + uno_Any * pSource = (uno_Any *)pSourceElements + nPos; + _copyConstructAny( + &pDestElements[nPos], + pSource->pData, + pSource->pType, 0, + acquire, 0 ); + } + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); + if (pSeq != 0) + { + char * pDestElements = pSeq->elements; + + typelib_CompoundTypeDescription * pTypeDescr = + (typelib_CompoundTypeDescription *)pElementTypeDescr; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + char * pDest = + pDestElements + (nElementSize * nPos); + char * pSource = + (char *)pSourceElements + (nElementSize * nPos); + + if (pTypeDescr->pBaseTypeDescription) + { + // copy base value + _copyConstructStruct( + pDest, pSource, + pTypeDescr->pBaseTypeDescription, acquire, 0 ); + } + + // then copy members + typelib_TypeDescriptionReference ** ppTypeRefs = + pTypeDescr->ppTypeRefs; + sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; + sal_Int32 nDescr = pTypeDescr->nMembers; + + while (nDescr--) + { + ::uno_type_copyData( + pDest + pMemberOffsets[nDescr], + pSource + pMemberOffsets[nDescr], + ppTypeRefs[nDescr], acquire ); + } + } + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_UNION: + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + sal_Int32 nElementSize = pElementTypeDescr->nSize; + + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); + if (pSeq != 0) + { + char * pDestElements = pSeq->elements; + + sal_Int32 nValueOffset = + ((typelib_UnionTypeDescription *) + pElementTypeDescr)->nValueOffset; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + char * pDest = + pDestElements + (nElementSize * nPos); + char * pSource = + (char *)pSourceElements + (nElementSize * nPos); + + typelib_TypeDescriptionReference * pSetType = _unionGetSetType( + pSource, pElementTypeDescr ); + ::uno_type_copyData( + pDest + nValueOffset, + pSource + nValueOffset, + pSetType, acquire ); + *(sal_Int64 *)pDest = *(sal_Int64 *)pSource; + typelib_typedescriptionreference_release( pSetType ); + } + } + + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + break; + } + case typelib_TypeClass_SEQUENCE: // sequence of sequence + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc ); + if (pSeq != 0) + { + typelib_TypeDescription * pElementTypeDescr = 0; + TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); + typelib_TypeDescriptionReference * pSeqElementType = + ((typelib_IndirectTypeDescription *) pElementTypeDescr)->pType; + uno_Sequence ** pDestElements = (uno_Sequence **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + uno_Sequence * pNew = icopyConstructSequence( + ((uno_Sequence **) pSourceElements)[nPos], + pSeqElementType, acquire, 0 ); + OSL_ASSERT( pNew != 0 ); + // ought never be a memory allocation problem, + // because of reference counted sequence handles + pDestElements[ nPos ] = pNew; + } + TYPELIB_DANGER_RELEASE( pElementTypeDescr ); + } + break; + } + case typelib_TypeClass_INTERFACE: + { + if (nAlloc >= 0) + pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc ); + if (pSeq != 0) + { + void ** pDestElements = (void **) pSeq->elements; + for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) + { + _acquire( pDestElements[nPos] = + ((void **)pSourceElements)[nPos], acquire ); + } + } + break; + } + default: + OSL_ENSURE( 0, "### unexpected element type!" ); + pSeq = 0; + break; + } + + if (pSeq == 0) + { + OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure + return false; + } + else + { + *ppSeq = pSeq; + return true; + } +} + +//------------------------------------------------------------------------------ +static inline bool ireallocSequence( + uno_Sequence ** ppSequence, + typelib_TypeDescriptionReference * pElementType, + sal_Int32 nSize, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) +{ + bool ret = true; + uno_Sequence * pSeq = *ppSequence; + sal_Int32 nElements = pSeq->nElements; + + if (pSeq->nRefCount > 1 || + // not mem-copyable elements? + typelib_TypeClass_ANY == pElementType->eTypeClass || + typelib_TypeClass_STRUCT == pElementType->eTypeClass || + typelib_TypeClass_EXCEPTION == pElementType->eTypeClass) + { + // split sequence and construct new one from scratch + uno_Sequence * pNew = 0; + + sal_Int32 nRest = nSize - nElements; + sal_Int32 nCopy = (nRest > 0 ? nElements : nSize); + + if (nCopy >= 0) + { + ret = icopyConstructFromElements( + &pNew, pSeq->elements, pElementType, + 0, nCopy, acquire, + nSize ); // alloc to nSize + } + if (ret && nRest > 0) + { + ret = idefaultConstructElements( + &pNew, pElementType, + nCopy, nSize, + nCopy >= 0 ? -1 /* no mem allocation */ : nSize ); + } + + if (ret) + { + // destruct sequence + if (osl_decrementInterlockedCount( &pSeq->nRefCount ) == 0) + { + if (nElements > 0) + { + idestructElements( + pSeq->elements, pElementType, + 0, nElements, release ); + } + rtl_freeMemory( pSeq ); + } + *ppSequence = pNew; + } + } + else + { + OSL_ASSERT( pSeq->nRefCount == 1 ); + if (nSize > nElements) // default construct the rest + { + ret = idefaultConstructElements( + ppSequence, pElementType, + nElements, nSize, + nSize ); // realloc to nSize + } + else // or destruct the rest and realloc mem + { + sal_Int32 nElementSize = idestructElements( + pSeq->elements, pElementType, + nSize, nElements, release ); + // warning: it is assumed that the following will never fail, + // else this leads to a sequence null handle + *ppSequence = reallocSeq( pSeq, nElementSize, nSize ); + OSL_ASSERT( *ppSequence != 0 ); + ret = (*ppSequence != 0); + } + } + + return ret; +} + +} + +extern "C" +{ + +//############################################################################## +sal_Bool SAL_CALL uno_type_sequence_construct( + uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType, + void * pElements, sal_Int32 len, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + bool ret; + if (len) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + + typelib_TypeDescriptionReference * pElementType = + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; + + *ppSequence = 0; + if (pElements == 0) + { + ret = idefaultConstructElements( + ppSequence, pElementType, + 0, len, + len ); // alloc to len + } + else + { + ret = icopyConstructFromElements( + ppSequence, pElements, pElementType, + 0, len, acquire, + len ); // alloc to len + } + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + else + { + *ppSequence = createEmptySequence(); + ret = true; + } + + OSL_ASSERT( (*ppSequence != 0) == ret ); + return ret; +} + +//############################################################################## +sal_Bool SAL_CALL uno_sequence_construct( + uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr, + void * pElements, sal_Int32 len, + uno_AcquireFunc acquire ) + SAL_THROW_EXTERN_C() +{ + bool ret; + if (len > 0) + { + typelib_TypeDescriptionReference * pElementType = + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; + + *ppSequence = 0; + if (pElements == 0) + { + ret = idefaultConstructElements( + ppSequence, pElementType, + 0, len, + len ); // alloc to len + } + else + { + ret = icopyConstructFromElements( + ppSequence, pElements, pElementType, + 0, len, acquire, + len ); // alloc to len + } + } + else + { + *ppSequence = createEmptySequence(); + ret = true; + } + + OSL_ASSERT( (*ppSequence != 0) == ret ); + return ret; +} + +//############################################################################## +sal_Bool SAL_CALL uno_type_sequence_realloc( + uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType, + sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppSequence, "### null ptr!" ); + OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" ); + + bool ret = true; + if (nSize != (*ppSequence)->nElements) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + ret = ireallocSequence( + ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + nSize, acquire, release ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + return ret; +} + +//############################################################################## +sal_Bool SAL_CALL uno_sequence_realloc( + uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr, + sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppSequence, "### null ptr!" ); + OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" ); + + bool ret = true; + if (nSize != (*ppSequence)->nElements) + { + ret = ireallocSequence( + ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + nSize, acquire, release ); + } + return ret; +} + +//############################################################################## +sal_Bool SAL_CALL uno_type_sequence_reference2One( + uno_Sequence ** ppSequence, + typelib_TypeDescriptionReference * pType, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppSequence, "### null ptr!" ); + bool ret = true; + uno_Sequence * pSequence = *ppSequence; + if (pSequence->nRefCount > 1) + { + uno_Sequence * pNew = 0; + if (pSequence->nElements > 0) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pType ); + + ret = icopyConstructFromElements( + &pNew, pSequence->elements, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + 0, pSequence->nElements, acquire, + pSequence->nElements ); // alloc nElements + if (ret) + { + idestructSequence( *ppSequence, pType, pTypeDescr, release ); + *ppSequence = pNew; + } + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + else + { + pNew = allocSeq( 0, 0 ); + ret = (pNew != 0); + if (ret) + { + // easy destruction of empty sequence: + if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0) + rtl_freeMemory( pSequence ); + *ppSequence = pNew; + } + } + } + return ret; +} + +//############################################################################## +sal_Bool SAL_CALL uno_sequence_reference2One( + uno_Sequence ** ppSequence, + typelib_TypeDescription * pTypeDescr, + uno_AcquireFunc acquire, uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + OSL_ENSURE( ppSequence, "### null ptr!" ); + bool ret = true; + uno_Sequence * pSequence = *ppSequence; + if (pSequence->nRefCount > 1) + { + uno_Sequence * pNew = 0; + if (pSequence->nElements > 0) + { + ret = icopyConstructFromElements( + &pNew, pSequence->elements, + ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, + 0, pSequence->nElements, acquire, + pSequence->nElements ); // alloc nElements + if (ret) + { + idestructSequence( + pSequence, pTypeDescr->pWeakRef, pTypeDescr, release ); + *ppSequence = pNew; + } + } + else + { + pNew = allocSeq( 0, 0 ); + ret = (pNew != 0); + if (ret) + { + // easy destruction of empty sequence: + if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0) + rtl_freeMemory( pSequence ); + *ppSequence = pNew; + } + } + + } + return ret; +} + +//############################################################################## +void SAL_CALL uno_sequence_assign( + uno_Sequence ** ppDest, + uno_Sequence * pSource, + typelib_TypeDescription * pTypeDescr, + uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + if (*ppDest != pSource) + { + ::osl_incrementInterlockedCount( &pSource->nRefCount ); + idestructSequence( *ppDest, pTypeDescr->pWeakRef, pTypeDescr, release ); + *ppDest = pSource; + } +} + +//############################################################################## +void SAL_CALL uno_type_sequence_assign( + uno_Sequence ** ppDest, + uno_Sequence * pSource, + typelib_TypeDescriptionReference * pType, + uno_ReleaseFunc release ) + SAL_THROW_EXTERN_C() +{ + if (*ppDest != pSource) + { + ::osl_incrementInterlockedCount( &pSource->nRefCount ); + idestructSequence( *ppDest, pType, 0, release ); + *ppDest = pSource; + } +} + +} |