1
0
Fork 0
libreoffice/bridges/source/net_uno/net_data.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

855 lines
35 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "net_bridge.hxx"
#include "net_proxy.hxx"
#include <cstring>
#include <unordered_map>
#include <vector>
#include <bridges/net_uno/net_context.hxx>
namespace net_uno
{
namespace
{
size_t net_sizeof(typelib_TypeClass eTypeClass)
{
static const std::unordered_map<typelib_TypeClass, size_t> s_sizes{
{ typelib_TypeClass_BOOLEAN, sizeof(sal_Bool) },
{ typelib_TypeClass_BYTE, sizeof(sal_Int8) },
{ typelib_TypeClass_CHAR, sizeof(sal_Unicode) },
{ typelib_TypeClass_SHORT, sizeof(sal_Int16) },
{ typelib_TypeClass_UNSIGNED_SHORT, sizeof(sal_uInt16) },
{ typelib_TypeClass_LONG, sizeof(sal_Int32) },
{ typelib_TypeClass_UNSIGNED_LONG, sizeof(sal_uInt32) },
{ typelib_TypeClass_HYPER, sizeof(sal_Int64) },
{ typelib_TypeClass_UNSIGNED_HYPER, sizeof(sal_uInt64) },
{ typelib_TypeClass_FLOAT, sizeof(float) },
{ typelib_TypeClass_DOUBLE, sizeof(double) },
{ typelib_TypeClass_ENUM, sizeof(sal_Int32) },
{ typelib_TypeClass_STRING, sizeof(IntPtr) },
{ typelib_TypeClass_TYPE, sizeof(IntPtr) },
{ typelib_TypeClass_ANY, sizeof(IntPtr) + sizeof(IntPtr) },
{ typelib_TypeClass_SEQUENCE, sizeof(IntPtr) + sizeof(sal_Int32) },
{ typelib_TypeClass_INTERFACE, sizeof(IntPtr) },
{ typelib_TypeClass_EXCEPTION, sizeof(IntPtr) },
{ typelib_TypeClass_STRUCT, sizeof(IntPtr) },
};
return s_sizes.at(eTypeClass);
}
IntPtr alloc_net_string(const OUString& str)
{
const sal_Unicode* src = str.getStr();
sal_Int32 len = str.getLength();
void* dst = std::malloc((len + 1) * sizeof(sal_Unicode));
std::memcpy(dst, src, len * sizeof(sal_Unicode));
static_cast<sal_Unicode*>(dst)[len] = u'\0';
return dst;
}
uno_Sequence* alloc_uno_sequence(sal_Int32 nElements, sal_Int32 nElementSize, void* data)
{
void* mem = std::malloc(SAL_SEQUENCE_HEADER_SIZE + nElements * nElementSize);
uno_Sequence* seq = static_cast<uno_Sequence*>(mem);
seq->nRefCount = 1;
seq->nElements = nElements;
if (data)
std::memcpy(seq->elements, data, nElements * nElementSize);
return seq;
}
void marshal_data(void* pUnoData, void* pNetData, typelib_TypeDescriptionReference* pTDRef,
bool bDestructValue, Bridge& bridge)
{
switch (pTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
std::memcpy(pNetData, pUnoData, net_sizeof(pTDRef->eTypeClass));
break;
case typelib_TypeClass_STRING:
{
IntPtr* ppNetStr = static_cast<IntPtr*>(pNetData);
rtl_uString* pUnoStr = *static_cast<rtl_uString**>(pUnoData);
if (bDestructValue && pNetData)
std::free(pNetData);
*ppNetStr = alloc_net_string(OUString::unacquired(&pUnoStr));
break;
}
case typelib_TypeClass_TYPE:
{
IntPtr* ppNetType = static_cast<IntPtr*>(pNetData);
typelib_TypeDescriptionReference* pUnoType
= *static_cast<typelib_TypeDescriptionReference**>(pUnoData);
if (bDestructValue && pNetData)
std::free(pNetData);
*ppNetType = alloc_net_string(map_uno_type_to_net(pUnoType));
break;
}
case typelib_TypeClass_ANY:
{
Value::Any* ppNetAny = static_cast<Value::Any*>(pNetData);
uno_Any* pUnoAny = static_cast<uno_Any*>(pUnoData);
if (bDestructValue && ppNetAny->type)
std::free(ppNetAny->type);
if (bDestructValue && ppNetAny->data)
std::free(ppNetAny->data);
ppNetAny->type = alloc_net_string(map_uno_type_to_net(pUnoAny->pType));
switch (pUnoAny->pType->eTypeClass)
{
case typelib_TypeClass_VOID:
ppNetAny->data = nullptr;
break;
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_FLOAT:
case typelib_TypeClass_ENUM:
std::memcpy(&ppNetAny->data, pUnoAny->pData, sizeof(IntPtr));
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
{
size_t size = net_sizeof(pUnoAny->pType->eTypeClass);
if (size <= sizeof(IntPtr))
{
std::memcpy(&ppNetAny->data, pUnoAny->pData, sizeof(IntPtr));
}
else
{
IntPtr mem = std::malloc(size);
std::memcpy(mem, pUnoAny->pData, size);
std::free(ppNetAny->data);
ppNetAny->data = mem;
}
break;
}
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
{
IntPtr mem = std::malloc(net_sizeof(pUnoAny->pType->eTypeClass));
marshal_data(pUnoAny->pData, mem, pUnoAny->pType, bDestructValue, bridge);
std::free(ppNetAny->data);
ppNetAny->data = mem;
break;
}
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
marshal_data(pUnoAny->pData, &ppNetAny->data, pUnoAny->pType, bDestructValue,
bridge);
break;
default:
{
throw BridgeRuntimeError(SAL_WHERE,
"could not map "
+ OUString::unacquired(&pUnoAny->pType->pTypeName)
+ " out of an UNO any");
}
}
break;
}
case typelib_TypeClass_SEQUENCE:
{
Value::Sequence* ppNetSeq = static_cast<Value::Sequence*>(pNetData);
uno_Sequence* pUnoSeq = *static_cast<uno_Sequence**>(pUnoData);
if (bDestructValue && ppNetSeq->data)
std::free(ppNetSeq->data);
ppNetSeq->length = pUnoSeq->nElements;
TypeDescHolder type(pTDRef);
typelib_TypeDescriptionReference* pElemTDRef
= reinterpret_cast<typelib_IndirectTypeDescription*>(type.get())->pType;
size_t nNetElemSize = net_sizeof(pElemTDRef->eTypeClass);
switch (pElemTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
{
ppNetSeq->data = std::malloc(nNetElemSize * ppNetSeq->length);
std::memcpy(ppNetSeq->data, pUnoSeq->elements, nNetElemSize * ppNetSeq->length);
break;
}
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
{
TypeDescHolder elemType(pElemTDRef);
sal_Int32 nUnoElemSize = elemType.get()->nSize;
ppNetSeq->data = std::malloc(nUnoElemSize * ppNetSeq->length);
// Convert each element
for (int nPos = 0; nPos < ppNetSeq->length; ++nPos)
{
void* pNetElem = static_cast<char*>(ppNetSeq->data) + (nPos * nNetElemSize);
void* pUnoElem = pUnoSeq->elements + (nPos * nUnoElemSize);
marshal_data(pUnoElem, pNetElem, pElemTDRef, bDestructValue, bridge);
}
break;
}
default:
{
throw BridgeRuntimeError(
SAL_WHERE, "could not map " + OUString::unacquired(&pElemTDRef->pTypeName)
+ " out of an UNO sequence");
}
}
break;
}
case typelib_TypeClass_INTERFACE:
{
IntPtr* ppNetI = static_cast<IntPtr*>(pNetData);
uno_Interface* pUnoI = *static_cast<uno_Interface**>(pUnoData);
if (pUnoI)
{
Context* pCtx = static_cast<Context*>(bridge.m_net_env->pContext);
// Get oid and type name
rtl_uString* pOid = nullptr;
(*bridge.m_uno_env->getObjectIdentifier)(bridge.m_uno_env, &pOid, pUnoI);
const OUString& sOid = OUString::unacquired(&pOid);
OUString sTypeName = map_uno_type_to_net(pTDRef);
// Get the proxy if already created, else create new
*ppNetI = pCtx->lookupInterface(sOid.getStr(), sTypeName.getStr());
if (!*ppNetI)
{
TypeDescHolder type(pTDRef);
typelib_InterfaceTypeDescription* pTD
= reinterpret_cast<typelib_InterfaceTypeDescription*>(type.get());
// TODO: check whether lifetime control is correct
bridge.acquire();
(*pUnoI->acquire)(pUnoI);
typelib_typedescription_acquire(&pTD->aBase);
(*bridge.m_uno_env->registerInterface)(
bridge.m_uno_env, reinterpret_cast<void**>(&pUnoI), pOid, pTD);
*ppNetI
= pCtx->createProxy(sOid.getStr(), sTypeName.getStr(), &bridge, pUnoI, pTD);
}
}
else
{
*ppNetI = nullptr;
}
break;
}
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
{
IntPtr* ppNetStruct = static_cast<IntPtr*>(pNetData);
void* pUnoStruct = pUnoData;
if (bDestructValue && *ppNetStruct)
std::free(*ppNetStruct);
TypeDescHolder type(pTDRef);
typelib_CompoundTypeDescription* pCompTD
= reinterpret_cast<typelib_CompoundTypeDescription*>(type.get());
if (!type.get()->bComplete)
typelib_typedescription_complete(
reinterpret_cast<typelib_TypeDescription**>(&pCompTD));
size_t nBytes = 0;
std::vector<std::pair<typelib_TypeDescriptionReference*, sal_Int32>> vecMembers;
for (typelib_CompoundTypeDescription* pHierTD = pCompTD; pHierTD;
pHierTD = pHierTD->pBaseTypeDescription)
{
for (int n = pHierTD->nMembers - 1; n >= 0; n--)
{
vecMembers.emplace_back(pHierTD->ppTypeRefs[n], pHierTD->pMemberOffsets[n]);
nBytes += net_sizeof(pHierTD->ppTypeRefs[n]->eTypeClass);
}
}
*ppNetStruct = std::malloc(nBytes);
size_t nNetOffset = 0;
int nPos = vecMembers.size() - 1;
for (; nPos >= 0; nPos--)
{
auto[pMemberTDRef, nUnoOffset] = vecMembers[nPos];
void* pUnoField = static_cast<char*>(pUnoStruct) + nUnoOffset;
void* pNetField = static_cast<char*>(*ppNetStruct) + nNetOffset;
switch (pMemberTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
std::memcpy(pNetField, pUnoField, net_sizeof(pMemberTDRef->eTypeClass));
break;
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
marshal_data(pUnoField, pNetField, pMemberTDRef, bDestructValue, bridge);
break;
default:
{
throw BridgeRuntimeError(
SAL_WHERE,
"could not map " + OUString::unacquired(&pMemberTDRef->pTypeName)
+ " out of an UNO " + OUString::unacquired(&pTDRef->pTypeName));
}
}
nNetOffset += net_sizeof(pMemberTDRef->eTypeClass);
}
break;
}
default:
{
throw BridgeRuntimeError(SAL_WHERE, "could not map "
+ OUString::unacquired(&pTDRef->pTypeName)
+ " value to .NET");
}
}
}
void unmarshal_data(void* pUnoData, void* pNetData, typelib_TypeDescriptionReference* pTDRef,
bool bDestructObject, bool bAssignData, Bridge& bridge)
{
switch (pTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
if (bAssignData)
std::memcpy(pUnoData, pNetData, net_sizeof(pTDRef->eTypeClass));
break;
case typelib_TypeClass_STRING:
{
rtl_uString** ppUnoStr = static_cast<rtl_uString**>(pUnoData);
IntPtr pNetStr = *static_cast<IntPtr*>(pNetData);
if (bDestructObject && ppUnoStr)
rtl_uString_release(*ppUnoStr);
if (bAssignData)
{
*ppUnoStr = nullptr;
if (pNetStr)
rtl_uString_newFromStr(ppUnoStr, static_cast<String>(pNetStr));
else
rtl_uString_new(ppUnoStr);
}
std::free(pNetStr);
break;
}
case typelib_TypeClass_TYPE:
{
typelib_TypeDescriptionReference** ppUnoType
= static_cast<typelib_TypeDescriptionReference**>(pUnoData);
IntPtr pNetType = *static_cast<IntPtr*>(pNetData);
if (bDestructObject && ppUnoType)
typelib_typedescriptionreference_release(*ppUnoType);
if (bAssignData)
*ppUnoType = map_net_type_to_uno(OUString(static_cast<String>(pNetType)));
std::free(pNetType);
break;
}
case typelib_TypeClass_ANY:
{
uno_Any* pUnoAny = static_cast<uno_Any*>(pUnoData);
Value::Any* pNetAny = static_cast<Value::Any*>(pNetData);
if (bDestructObject && pUnoData)
uno_any_destruct(pUnoAny, nullptr);
typelib_TypeDescriptionReference* pValueTDRef
= map_net_type_to_uno(OUString(static_cast<String>(pNetAny->type)));
std::free(pNetAny->type);
if (bAssignData)
{
switch (pValueTDRef->eTypeClass)
{
case typelib_TypeClass_VOID:
{
pUnoAny->pType = pValueTDRef;
pUnoAny->pData = &pUnoAny->pReserved;
break;
}
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_FLOAT:
case typelib_TypeClass_ENUM:
{
pUnoAny->pType = pValueTDRef;
pUnoAny->pData = &pUnoAny->pReserved;
std::memcpy(pUnoAny->pData, &pNetAny->data, sizeof(IntPtr));
break;
}
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
{
pUnoAny->pType = pValueTDRef;
size_t size = net_sizeof(pValueTDRef->eTypeClass);
if (size <= sizeof(IntPtr))
{
pUnoAny->pData = &pUnoAny->pReserved;
std::memcpy(pUnoAny->pData, &pNetAny->data, sizeof(IntPtr));
}
else
{
void* mem = std::malloc(size);
std::memcpy(mem, pNetAny->data, size);
pUnoAny->pData = mem;
std::free(pNetAny->data);
}
break;
}
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
{
if (pNetAny->data)
{
pUnoAny->pType = pValueTDRef;
pUnoAny->pData = &pUnoAny->pReserved;
pUnoAny->pReserved = nullptr;
unmarshal_data(pUnoAny->pData, &pNetAny->data, pValueTDRef,
bDestructObject, true, bridge);
}
else
{
uno_any_construct(pUnoAny, nullptr, nullptr, nullptr);
}
break;
}
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
{
if (pNetAny->data)
{
pUnoAny->pType = pValueTDRef;
pUnoAny->pData = &pUnoAny->pReserved;
pUnoAny->pReserved = nullptr;
unmarshal_data(pUnoAny->pData, &pNetAny->data, pValueTDRef,
bDestructObject, true, bridge);
}
else
{
uno_any_construct(pUnoAny, nullptr, nullptr, nullptr);
}
break;
}
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
{
if (pNetAny->data)
{
pUnoAny->pType = pValueTDRef;
TypeDescHolder valueType(pValueTDRef);
void* mem = std::malloc(valueType.get()->nSize);
unmarshal_data(mem, &pNetAny->data, pValueTDRef, bDestructObject, true,
bridge);
pUnoAny->pData = mem;
}
else
{
uno_any_construct(pUnoAny, nullptr, nullptr, nullptr);
}
break;
}
default:
{
throw BridgeRuntimeError(SAL_WHERE,
"could not map "
+ OUString::unacquired(&pValueTDRef->pTypeName)
+ " into an UNO any");
}
}
}
else
{
switch (pValueTDRef->eTypeClass)
{
case typelib_TypeClass_VOID:
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_FLOAT:
case typelib_TypeClass_ENUM:
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
case typelib_TypeClass_DOUBLE:
{
size_t size = net_sizeof(pValueTDRef->eTypeClass);
if (pNetAny->data && size > sizeof(IntPtr))
std::free(pNetAny->data);
break;
}
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
{
if (pNetAny->data)
{
unmarshal_data(pUnoAny->pData, &pNetAny->data, pValueTDRef,
bDestructObject, false, bridge);
std::free(pNetAny->data);
}
break;
}
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
{
if (pNetAny->data)
{
unmarshal_data(pUnoAny->pData, &pNetAny->data, pValueTDRef,
bDestructObject, false, bridge);
}
break;
}
default:
{
throw BridgeRuntimeError(SAL_WHERE,
"could not map "
+ OUString::unacquired(&pValueTDRef->pTypeName)
+ " into an UNO any");
}
}
}
break;
}
case typelib_TypeClass_SEQUENCE:
{
uno_Sequence** ppUnoSeq = static_cast<uno_Sequence**>(pUnoData);
Value::Sequence* pNetSeq = static_cast<Value::Sequence*>(pNetData);
TypeDescHolder type(pTDRef);
if (bDestructObject && ppUnoSeq)
uno_destructData(ppUnoSeq, type.get(), nullptr);
typelib_TypeDescriptionReference* pElemTDRef
= reinterpret_cast<typelib_IndirectTypeDescription*>(type.get())->pType;
size_t nNetElemSize = net_sizeof(pElemTDRef->eTypeClass);
switch (pElemTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
if (bAssignData)
*ppUnoSeq
= alloc_uno_sequence(pNetSeq->length, nNetElemSize, pNetSeq->data);
break;
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
{
TypeDescHolder elemType(pElemTDRef);
sal_Int32 nUnoElemSize = elemType.get()->nSize;
*ppUnoSeq = alloc_uno_sequence(pNetSeq->length, nUnoElemSize, nullptr);
int nPos = 0;
try
{
// Convert each element
for (; nPos < pNetSeq->length; ++nPos)
{
void* pNetElem
= static_cast<char*>(pNetSeq->data) + (nPos * nNetElemSize);
void* pUnoElem = (*ppUnoSeq)->elements + (nPos * nUnoElemSize);
unmarshal_data(pUnoElem, pNetElem, pElemTDRef, bDestructObject,
bAssignData, bridge);
}
}
catch (...)
{
if (bAssignData)
{
// Clean up already converted elements
for (int nClean = 0; nClean < nPos; ++nClean)
{
void* pUnoElem = (*ppUnoSeq)->elements + (nClean * nUnoElemSize);
uno_destructData(pUnoElem, elemType.get(), nullptr);
}
}
throw;
}
break;
}
default:
{
throw BridgeRuntimeError(
SAL_WHERE, "could not map " + OUString::unacquired(&pElemTDRef->pTypeName)
+ " into an UNO sequence");
}
}
std::free(pNetSeq->data);
break;
}
case typelib_TypeClass_INTERFACE:
{
uno_Interface** ppUnoI = static_cast<uno_Interface**>(pUnoData);
IntPtr pNetI = *static_cast<IntPtr*>(pNetData);
TypeDescHolder type(pTDRef);
if (bDestructObject && ppUnoI)
uno_destructData(ppUnoI, type.get(), nullptr);
if (bAssignData)
{
if (pNetI)
{
Context* pCtx = static_cast<Context*>(bridge.m_net_env->pContext);
// Get oid and type description
OUString sOid(pCtx->lookupObjectId(pNetI));
typelib_InterfaceTypeDescription* pInterfaceTD
= reinterpret_cast<typelib_InterfaceTypeDescription*>(type.get());
// Get the proxy if already created, else create new
*ppUnoI = nullptr;
(*bridge.m_uno_env->getRegisteredInterface)(bridge.m_uno_env,
reinterpret_cast<void**>(ppUnoI),
sOid.pData, pInterfaceTD);
if (!*ppUnoI)
*ppUnoI = new NetProxy(bridge, pNetI, pInterfaceTD, sOid);
}
else
{
*ppUnoI = nullptr;
}
}
break;
}
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
{
void* pUnoStruct = pUnoData;
IntPtr pNetStruct = *static_cast<IntPtr*>(pNetData);
TypeDescHolder type(pTDRef);
if (bDestructObject && pNetStruct)
uno_destructData(pNetStruct, type.get(), nullptr);
typelib_CompoundTypeDescription* pCompTD
= reinterpret_cast<typelib_CompoundTypeDescription*>(type.get());
if (!type.get()->bComplete)
typelib_typedescription_complete(
reinterpret_cast<typelib_TypeDescription**>(&pCompTD));
std::vector<std::pair<typelib_TypeDescriptionReference*, sal_Int32>> vecMembers;
for (typelib_CompoundTypeDescription* pHierTD = pCompTD; pHierTD;
pHierTD = pHierTD->pBaseTypeDescription)
{
for (int n = pHierTD->nMembers - 1; n >= 0; n--)
{
vecMembers.emplace_back(pHierTD->ppTypeRefs[n], pHierTD->pMemberOffsets[n]);
}
}
size_t nNetOffset = 0;
int nPos = vecMembers.size() - 1;
try
{
for (; nPos >= 0; nPos--)
{
auto[pMemberTDRef, nUnoOffset] = vecMembers[nPos];
void* pUnoField = static_cast<char*>(pUnoStruct) + nUnoOffset;
void* pNetField = static_cast<char*>(pNetStruct) + nNetOffset;
switch (pMemberTDRef->eTypeClass)
{
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_CHAR:
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_ENUM:
if (bAssignData)
std::memcpy(pUnoField, pNetField,
net_sizeof(pMemberTDRef->eTypeClass));
break;
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_INTERFACE:
case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_STRUCT:
unmarshal_data(pUnoField, pNetField, pMemberTDRef, bDestructObject,
bAssignData, bridge);
break;
default:
{
throw BridgeRuntimeError(
SAL_WHERE,
"could not map " + OUString::unacquired(&pMemberTDRef->pTypeName)
+ " into an UNO " + OUString::unacquired(&pTDRef->pTypeName));
}
}
nNetOffset += net_sizeof(pMemberTDRef->eTypeClass);
}
}
catch (...)
{
if (bAssignData)
{
// Clean up already converted fields
for (int nClean = vecMembers.size() - 1; nClean > nPos; nClean--)
{
auto[pMemberTDRef, nUnoOffset] = vecMembers[nClean];
void* pUnoField = static_cast<char*>(pUnoStruct) + nUnoOffset;
uno_type_destructData(pUnoField, pMemberTDRef, nullptr);
}
}
throw;
}
std::free(pNetStruct);
break;
}
default:
{
throw BridgeRuntimeError(SAL_WHERE, "could not map "
+ OUString::unacquired(&pTDRef->pTypeName)
+ " value to UNO");
}
}
}
}
void Bridge::map_uno_to_net_value(void* pUnoData, Value* pValue,
typelib_TypeDescriptionReference* pTDRef, bool bDestructValue)
{
marshal_data(pUnoData, pValue, pTDRef, bDestructValue, *this);
}
void Bridge::map_net_value_to_uno(void* pUnoData, Value* pValue,
typelib_TypeDescriptionReference* pTDRef, bool bDestructObject,
bool bAssignObject)
{
unmarshal_data(pUnoData, pValue, pTDRef, bDestructObject, bAssignObject, *this);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */