tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / cppu / source / helper / purpenv / helper_purpenv_Proxy.cxx
blobfc4f82daf07c11b00dfa370d3c4f0347973f962c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "Proxy.hxx"
23 #include <sal/log.hxx>
24 #include <uno/dispatcher.h>
25 #include <typelib/typedescription.hxx>
26 #include <utility>
28 using namespace com::sun::star;
30 static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
32 switch (pTypeDescr->eTypeClass)
34 // case typelib_TypeClass_TYPEDEF:
35 case typelib_TypeClass_SEQUENCE:
37 switch (reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType->eTypeClass)
39 case typelib_TypeClass_INTERFACE:
40 case typelib_TypeClass_ANY: // might relate to interface
41 return true;
42 case typelib_TypeClass_SEQUENCE:
43 case typelib_TypeClass_STRUCT:
44 case typelib_TypeClass_EXCEPTION:
46 typelib_TypeDescription * pTD = nullptr;
47 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
48 bool bRel = relatesToInterface( pTD );
49 TYPELIB_DANGER_RELEASE( pTD );
50 return bRel;
52 default:
55 return false;
57 case typelib_TypeClass_STRUCT:
58 case typelib_TypeClass_EXCEPTION:
60 // ...optimized... to avoid getDescription() calls!
61 typelib_CompoundTypeDescription * pComp = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
62 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
63 for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
65 switch (pTypes[nPos]->eTypeClass)
67 case typelib_TypeClass_INTERFACE:
68 case typelib_TypeClass_ANY: // might relate to interface
69 return true;
70 // case typelib_TypeClass_TYPEDEF:
71 case typelib_TypeClass_SEQUENCE:
72 case typelib_TypeClass_STRUCT:
73 case typelib_TypeClass_EXCEPTION:
75 typelib_TypeDescription * pTD = nullptr;
76 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
77 bool bRel = relatesToInterface( pTD );
78 TYPELIB_DANGER_RELEASE( pTD );
79 if (bRel)
80 return true;
81 break;
83 default:
84 break;
87 if (pComp->pBaseTypeDescription)
88 return relatesToInterface( &pComp->pBaseTypeDescription->aBase );
89 break;
91 case typelib_TypeClass_ANY: // might relate to interface
92 case typelib_TypeClass_INTERFACE:
93 return true;
95 default:
98 return false;
101 extern "C" { static void s_Proxy_dispatch(
102 uno_Interface * pUnoI,
103 typelib_TypeDescription const * pMemberType,
104 void * pReturn,
105 void * pArgs[],
106 uno_Any ** ppException) noexcept
108 Proxy * pThis = static_cast<Proxy *>(pUnoI);
110 typelib_MethodParameter param;
111 sal_Int32 nParams = 0;
112 typelib_MethodParameter * pParams = nullptr;
113 typelib_TypeDescriptionReference * pReturnTypeRef = nullptr;
114 // sal_Int32 nOutParams = 0;
116 switch (pMemberType->eTypeClass)
118 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
119 if (pReturn)
121 pReturnTypeRef =
122 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
123 pMemberType)->pAttributeTypeRef;
124 nParams = 0;
125 pParams = nullptr;
127 else
129 param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
130 pMemberType)->pAttributeTypeRef;
131 param.bIn = true;
132 param.bOut = false;
133 nParams = 1;
134 pParams = &param;
136 break;
137 case typelib_TypeClass_INTERFACE_METHOD:
139 typelib_InterfaceMethodTypeDescription const * method_td =
140 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType);
141 pReturnTypeRef = method_td->pReturnTypeRef;
142 nParams = method_td->nParams;
143 pParams = method_td->pParams;
144 break;
146 default:
147 OSL_FAIL( "### illegal member typeclass!" );
148 abort();
151 pThis->dispatch( pReturnTypeRef,
152 pParams,
153 nParams,
154 pMemberType,
155 pReturn,
156 pArgs,
157 ppException );
160 extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) noexcept
162 Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy));
163 delete pThis;
166 extern "C" {
167 static void s_Proxy_acquire(uno_Interface * pUnoI) noexcept
169 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
170 pProxy->acquire();
173 static void s_Proxy_release(uno_Interface * pUnoI) noexcept
175 Proxy * pProxy = static_cast<Proxy *>(pUnoI);
176 pProxy->release();
179 static void s_acquireAndRegister_v(va_list * pParam)
181 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
182 rtl_uString * pOid = va_arg(*pParam, rtl_uString *);
183 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
184 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
186 pUnoI->acquire(pUnoI);
187 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
191 Proxy::Proxy(uno::Mapping to_from,
192 uno_Environment * pTo,
193 uno_Environment * pFrom,
194 uno_Interface * pUnoI,
195 typelib_InterfaceTypeDescription * pTypeDescr,
196 OUString const & rOId,
197 cppu::helper::purpenv::ProbeFun * probeFun,
198 void * pProbeContext
200 : m_nRef (1),
201 m_from (pFrom),
202 m_to (pTo),
203 m_from_to (pFrom, pTo),
204 m_to_from (std::move(to_from)),
205 m_pUnoI (pUnoI),
206 m_pTypeDescr (pTypeDescr),
207 m_aOId (rOId),
208 m_probeFun (probeFun),
209 m_pProbeContext(pProbeContext)
211 SAL_INFO("cppu.purpenv", "LIFE: Proxy::Proxy(<>) -> " << this);
213 typelib_typedescription_acquire(&m_pTypeDescr->aBase);
214 if (!m_pTypeDescr->aBase.bComplete)
215 typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr));
217 OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!");
219 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
221 // uno_Interface
222 uno_Interface::acquire = s_Proxy_acquire;
223 uno_Interface::release = s_Proxy_release;
224 uno_Interface::pDispatcher = s_Proxy_dispatch;
227 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
229 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
230 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
232 pEnv->revokeInterface(pEnv, pUnoI);
233 pUnoI->release(pUnoI);
236 Proxy::~Proxy()
238 SAL_INFO("cppu.purpenv", "LIFE: Proxy::~Proxy() -> " << this);
240 uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
242 typelib_typedescription_release(&m_pTypeDescr->aBase);
245 static uno::TypeDescription getAcquireMethod()
247 typelib_TypeDescriptionReference * type_XInterface =
248 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
250 typelib_TypeDescription * pTXInterfaceDescr = nullptr;
251 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
252 uno::TypeDescription acquire(
253 reinterpret_cast< typelib_InterfaceTypeDescription * >(
254 pTXInterfaceDescr)->ppAllMembers[1]);
255 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
257 return acquire;
260 static uno::TypeDescription getReleaseMethod()
262 typelib_TypeDescriptionReference * type_XInterface =
263 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
265 typelib_TypeDescription * pTXInterfaceDescr = nullptr;
266 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface);
267 uno::TypeDescription release(
268 reinterpret_cast< typelib_InterfaceTypeDescription * >(
269 pTXInterfaceDescr)->ppAllMembers[2]);
270 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
272 return release;
275 static uno::TypeDescription s_acquireMethod(getAcquireMethod());
276 static uno::TypeDescription s_releaseMethod(getReleaseMethod());
278 void Proxy::acquire()
280 if (m_probeFun)
281 m_probeFun(true,
282 this,
283 m_pProbeContext,
284 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
285 nullptr,
287 s_acquireMethod.get(),
288 nullptr,
289 nullptr,
290 nullptr);
292 if (osl_atomic_increment(&m_nRef) == 1)
294 // rebirth of proxy zombie
295 void * pThis = this;
296 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
297 &pThis,
298 Proxy_free,
299 m_aOId.pData,
300 m_pTypeDescr);
301 OSL_ASSERT(pThis == this);
304 if (m_probeFun)
305 m_probeFun(false,
306 this,
307 m_pProbeContext,
308 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
309 nullptr,
311 s_acquireMethod.get(),
312 nullptr,
313 nullptr,
314 nullptr);
318 void Proxy::release()
320 cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
321 void * pProbeContext = m_pProbeContext;
323 if (m_probeFun)
324 m_probeFun(true,
325 this,
326 m_pProbeContext,
327 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
328 nullptr,
330 s_releaseMethod.get(),
331 nullptr,
332 nullptr,
333 nullptr);
335 if (osl_atomic_decrement(&m_nRef) == 0)
336 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
338 if (probeFun)
339 probeFun(false,
340 this,
341 pProbeContext,
342 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
343 nullptr,
345 s_releaseMethod.get(),
346 nullptr,
347 nullptr,
348 nullptr);
353 extern "C" {
354 static void s_type_destructData_v(va_list * pParam)
356 void * ret = va_arg(*pParam, void *);
357 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
359 uno_type_destructData(ret, pReturnTypeRef, nullptr);
362 static void s_dispatcher_v(va_list * pParam)
364 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
365 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
366 void * pReturn = va_arg(*pParam, void *);
367 void ** pArgs = va_arg(*pParam, void **);
368 uno_Any ** ppException = va_arg(*pParam, uno_Any **);
370 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
374 void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
375 typelib_MethodParameter * pParams,
376 sal_Int32 nParams,
377 typelib_TypeDescription const * pMemberType,
378 void * pReturn,
379 void * pArgs[],
380 uno_Any ** ppException)
382 if (m_probeFun)
383 m_probeFun(true,
384 this,
385 m_pProbeContext,
386 pReturnTypeRef,
387 pParams,
388 nParams,
389 pMemberType,
390 pReturn,
391 pArgs,
392 ppException);
394 void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams ));
396 typelib_TypeDescription * return_td = nullptr;
397 void * ret = pReturn;
398 if (pReturnTypeRef)
400 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
402 if (relatesToInterface(return_td))
403 ret = alloca(return_td->nSize);
405 TYPELIB_DANGER_RELEASE(return_td);
408 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
410 typelib_MethodParameter const & param = pParams[nPos];
411 typelib_TypeDescription * td = nullptr;
412 TYPELIB_DANGER_GET( &td, param.pTypeRef );
413 if (relatesToInterface(td))
415 args[nPos] = alloca(td->nSize);
416 if (param.bIn)
418 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
421 else
423 args[nPos] = pArgs[nPos];
425 TYPELIB_DANGER_RELEASE( td );
428 uno_Any exc_data;
429 uno_Any * exc = &exc_data;
431 // do the UNO call...
432 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
434 if (exc == nullptr)
436 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
438 if (args[nPos] != pArgs[nPos])
440 typelib_MethodParameter const & param = pParams[nPos];
441 if (param.bOut)
443 if (param.bIn) // is inout
445 uno_type_destructData(pArgs[nPos], param.pTypeRef, nullptr);
447 uno_type_copyAndConvertData(pArgs[ nPos ],
448 args[ nPos ],
449 param.pTypeRef,
450 m_to_from.get());
452 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
455 if (ret != pReturn)
457 uno_type_copyAndConvertData(pReturn,
458 ret,
459 pReturnTypeRef,
460 m_to_from.get());
462 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
465 *ppException = nullptr;
467 else // exception occurred
469 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
471 if (args[nPos] != pArgs[nPos])
473 typelib_MethodParameter const & param = pParams[nPos];
474 if (param.bIn)
476 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
481 uno_type_any_constructAndConvert(*ppException,
482 exc->pData,
483 exc->pType,
484 m_to_from.get());
486 // FIXME: need to destruct in m_to
487 uno_any_destruct(exc, nullptr);
490 if (m_probeFun)
491 m_probeFun(false,
492 this,
493 m_pProbeContext,
494 pReturnTypeRef,
495 pParams,
496 nParams,
497 pMemberType,
498 pReturn,
499 pArgs,
500 ppException);
503 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */