blob: b2b41016e95abcdd4f4739b09588f9fbd74d7b98 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "precompiled_bridges.hxx"
#include "sal/config.h"
#include <algorithm>
#include <cstddef>
#include <cstring>
#include "bridges/cpp_uno/shared/bridge.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
#include "bridges/cpp_uno/shared/vtables.hxx"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/genfunc.hxx"
#include "osl/diagnose.h"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/alloca.h"
#include "sal/types.h"
#include "typelib/typeclass.h"
#include "typelib/typedescription.h"
#include "uno/any2.h"
#include "uno/data.h"
#include "callvirtualmethod.hxx"
#include "exceptions.hxx"
#include "fp.hxx"
#include "isdirectreturntype.hxx"
namespace {
namespace css = com::sun::star;
void storeFpRegsToStruct(typelib_TypeDescription * type, void * data) {
for (typelib_CompoundTypeDescription * t =
reinterpret_cast< typelib_CompoundTypeDescription * >(type);
t != NULL; t = t->pBaseTypeDescription)
{
for (sal_Int32 i = 0; i < t->nMembers; ++i) {
switch (t->ppTypeRefs[i]->eTypeClass) {
case typelib_TypeClass_FLOAT:
switch (t->pMemberOffsets[i]) {
case 0:
fp_storef0(reinterpret_cast< float * >(data));
break;
case 4:
fp_storef1(reinterpret_cast< float * >(data) + 1);
break;
case 8:
fp_storef2(reinterpret_cast< float * >(data) + 2);
break;
case 12:
fp_storef3(reinterpret_cast< float * >(data) + 3);
break;
case 16:
fp_storef4(reinterpret_cast< float * >(data) + 4);
break;
case 20:
fp_storef5(reinterpret_cast< float * >(data) + 5);
break;
case 24:
fp_storef6(reinterpret_cast< float * >(data) + 6);
break;
case 28:
fp_storef7(reinterpret_cast< float * >(data) + 7);
break;
default:
OSL_ASSERT(false);
break;
}
break;
case typelib_TypeClass_DOUBLE:
switch (t->pMemberOffsets[i]) {
case 0:
fp_stored0(reinterpret_cast< double * >(data));
break;
case 8:
fp_stored2(reinterpret_cast< double * >(data) + 1);
break;
case 16:
fp_stored4(reinterpret_cast< double * >(data) + 2);
break;
case 24:
fp_stored6(reinterpret_cast< double * >(data) + 3);
break;
default:
OSL_ASSERT(false);
break;
}
break;
case typelib_TypeClass_STRUCT:
{
typelib_TypeDescription * td = NULL;
TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]);
storeFpRegsToStruct(td, data);
TYPELIB_DANGER_RELEASE(td);
break;
}
}
}
}
}
void call(
bridges::cpp_uno::shared::UnoInterfaceProxy * proxy,
bridges::cpp_uno::shared::VtableSlot slot,
typelib_TypeDescriptionReference * returnType, sal_Int32 count,
typelib_MethodParameter * parameters, void * returnValue, void ** arguments,
uno_Any ** exception)
{
bool directRet = bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType(
returnType);
long * stack = static_cast< long * >(
alloca(
std::max< sal_Int32 >(count + (directRet ? 1 : 2), 4) *
sizeof (long)));
sal_Int32 sp = 0;
typelib_TypeDescription * rtd = NULL;
TYPELIB_DANGER_GET(&rtd, returnType);
bool retconv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
OSL_ASSERT(!(directRet && retconv));
void * ret;
if (!directRet) {
ret = retconv ? alloca(rtd->nSize) : returnValue;
stack[sp++] = reinterpret_cast< long >(ret);
}
unsigned long ** thisPtr = reinterpret_cast< unsigned long ** >(
proxy->getCppI()) + slot.offset;
stack[sp++] = reinterpret_cast< long >(thisPtr);
void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *)));
typelib_TypeDescription ** ptds =
static_cast< typelib_TypeDescription ** >(
alloca(count * sizeof (typelib_TypeDescription *)));
for (sal_Int32 i = 0; i < count; ++i) {
if (!parameters[i].bOut &&
bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
{
cppArgs[i] = NULL;
switch (parameters[i].pTypeRef->eTypeClass) {
case typelib_TypeClass_BOOLEAN:
stack[sp] = *static_cast< sal_Bool * >(arguments[i]);
break;
case typelib_TypeClass_BYTE:
stack[sp] = *static_cast< sal_Int8 * >(arguments[i]);
break;
case typelib_TypeClass_SHORT:
stack[sp] = *static_cast< sal_Int16 * >(arguments[i]);
break;
case typelib_TypeClass_UNSIGNED_SHORT:
stack[sp] = *static_cast< sal_uInt16 * >(arguments[i]);
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_ENUM:
stack[sp] = *static_cast< sal_Int32 * >(arguments[i]);
break;
case typelib_TypeClass_UNSIGNED_LONG:
stack[sp] = *static_cast< sal_uInt32 * >(arguments[i]);
break;
case typelib_TypeClass_HYPER:
stack[sp] = *static_cast< sal_Int64 * >(arguments[i]);
break;
case typelib_TypeClass_UNSIGNED_HYPER:
stack[sp] = *static_cast< sal_uInt64 * >(arguments[i]);
break;
case typelib_TypeClass_FLOAT:
{
float * f = static_cast< float * >(arguments[i]);
switch (sp) {
case 1:
fp_loadf3(f);
break;
case 2:
fp_loadf5(f);
break;
case 3:
fp_loadf7(f);
break;
case 4:
fp_loadf9(f);
break;
case 5:
fp_loadf11(f);
break;
case 6:
fp_loadf13(f);
break;
case 7:
fp_loadf15(f);
break;
case 8:
fp_loadf17(f);
break;
case 9:
fp_loadf19(f);
break;
case 10:
fp_loadf21(f);
break;
case 11:
fp_loadf23(f);
break;
case 12:
fp_loadf25(f);
break;
case 13:
fp_loadf27(f);
break;
case 14:
fp_loadf29(f);
break;
case 15:
fp_loadf31(f);
break;
default:
reinterpret_cast< float * >(stack + sp)[1] = *f;
break;
}
break;
}
case typelib_TypeClass_DOUBLE:
{
double * d = static_cast< double * >(arguments[i]);
switch (sp) {
case 1:
fp_loadd2(d);
break;
case 2:
fp_loadd4(d);
break;
case 3:
fp_loadd6(d);
break;
case 4:
fp_loadd8(d);
break;
case 5:
fp_loadd10(d);
break;
case 6:
fp_loadd12(d);
break;
case 7:
fp_loadd14(d);
break;
case 8:
fp_loadd16(d);
break;
case 9:
fp_loadd18(d);
break;
case 10:
fp_loadd20(d);
break;
case 11:
fp_loadd22(d);
break;
case 12:
fp_loadd24(d);
break;
case 13:
fp_loadd26(d);
break;
case 14:
fp_loadd28(d);
break;
case 15:
fp_loadd30(d);
break;
default:
*reinterpret_cast< double * >(stack + sp) = *d;
break;
}
break;
}
case typelib_TypeClass_CHAR:
stack[sp] = *static_cast< sal_Unicode * >(arguments[i]);
break;
default:
OSL_ASSERT(false);
break;
}
} else {
typelib_TypeDescription * ptd = NULL;
TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
if (!parameters[i].bIn) {
cppArgs[i] = alloca(ptd->nSize);
uno_constructData(cppArgs[i], ptd);
ptds[i] = ptd;
*reinterpret_cast< void ** >(stack + sp) = cppArgs[i];
} else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
cppArgs[i] = alloca(ptd->nSize);
uno_copyAndConvertData(
cppArgs[i], arguments[i], ptd,
proxy->getBridge()->getUno2Cpp());
ptds[i] = ptd;
*reinterpret_cast< void ** >(stack + sp) = cppArgs[i];
} else {
cppArgs[i] = NULL;
*reinterpret_cast< void ** >(stack + sp) = arguments[i];
TYPELIB_DANGER_RELEASE(ptd);
}
}
++sp;
}
try {
callVirtualMethod(
(*thisPtr)[slot.index + 2], stack,
std::max< sal_Int32 >(sp - 6, 0) * sizeof (long));
} catch (css::uno::Exception &) {
void * exc = __Crun::ex_get();
char const * name = __Cimpl::ex_name();
bridges::cpp_uno::cc5_solaris_sparc64::fillUnoException(
exc, name, *exception, proxy->getBridge()->getCpp2Uno());
for (sal_Int32 i = 0; i < count; ++i) {
if (cppArgs[i] != NULL) {
uno_destructData(
cppArgs[i], ptds[i],
reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
TYPELIB_DANGER_RELEASE(ptds[i]);
}
}
TYPELIB_DANGER_RELEASE(rtd);
return;
}
*exception = NULL;
for (sal_Int32 i = 0; i < count; ++i) {
if (cppArgs[i] != NULL) {
if (parameters[i].bOut) {
if (parameters[i].bIn) {
uno_destructData(arguments[i], ptds[i], NULL);
}
uno_copyAndConvertData(
arguments[i], cppArgs[i], ptds[i],
proxy->getBridge()->getCpp2Uno());
}
uno_destructData(
cppArgs[i], ptds[i],
reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
TYPELIB_DANGER_RELEASE(ptds[i]);
}
}
if (directRet) {
switch (rtd->eTypeClass) {
case typelib_TypeClass_FLOAT:
fp_storef0(reinterpret_cast< float * >(returnValue));
break;
case typelib_TypeClass_DOUBLE:
fp_stored0(reinterpret_cast< double * >(returnValue));
break;
case typelib_TypeClass_STRUCT:
storeFpRegsToStruct(rtd, stack);
// fall through
case typelib_TypeClass_ANY:
std::memcpy(returnValue, stack, rtd->nSize);
break;
default:
OSL_ASSERT(rtd->nSize <= 8);
std::memcpy(
returnValue,
reinterpret_cast< char * >(stack) + (8 - rtd->nSize),
rtd->nSize);
break;
}
} else if (retconv) {
uno_copyAndConvertData(
returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno());
uno_destructData(
ret, rtd,
reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
}
TYPELIB_DANGER_RELEASE(rtd);
}
}
namespace bridges { namespace cpp_uno { namespace shared {
void unoInterfaceProxyDispatch(
uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr,
void * pReturn, void * pArgs[], uno_Any ** ppException)
{
bridges::cpp_uno::shared::UnoInterfaceProxy * proxy =
static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
switch (pMemberDescr->eTypeClass) {
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
VtableSlot slot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(
pMemberDescr)));
if (pReturn != NULL) {
// Getter:
call(
proxy, slot,
(reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(
pMemberDescr)->pAttributeTypeRef),
0, NULL, pReturn, pArgs, ppException);
} else {
// Setter:
typelib_MethodParameter param = {
NULL,
(reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(
pMemberDescr)->pAttributeTypeRef),
true, false };
typelib_TypeDescriptionReference * rtd = NULL;
typelib_typedescriptionreference_new(
&rtd, typelib_TypeClass_VOID,
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")).pData);
slot.index += 1;
call(proxy, slot, rtd, 1, &param, pReturn, pArgs, ppException);
typelib_typedescriptionreference_release(rtd);
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
VtableSlot slot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)));
switch (slot.index) {
case 1:
pUnoI->acquire(pUnoI);
*ppException = NULL;
break;
case 2:
pUnoI->release(pUnoI);
*ppException = NULL;
break;
case 0:
{
typelib_TypeDescription * td = NULL;
TYPELIB_DANGER_GET(
&td,
reinterpret_cast< css::uno::Type * >(
pArgs[0])->getTypeLibType());
if (td != NULL) {
uno_Interface * ifc = NULL;
proxy->pBridge->getUnoEnv()->getRegisteredInterface(
proxy->pBridge->getUnoEnv(),
reinterpret_cast< void ** >(&ifc),
proxy->oid.pData,
(reinterpret_cast<
typelib_InterfaceTypeDescription * >(td)));
if (ifc != NULL) {
uno_any_construct(
reinterpret_cast< uno_Any * >(pReturn),
&ifc, td, NULL);
ifc->release(ifc);
TYPELIB_DANGER_RELEASE(td);
*ppException = NULL;
break;
}
TYPELIB_DANGER_RELEASE(td);
}
} // fall through
default:
call(
proxy, slot,
(reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)->pReturnTypeRef),
(reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)->nParams),
(reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)->pParams),
pReturn, pArgs, ppException);
}
break;
}
default:
OSL_ASSERT(false);
break;
}
}
} } }