summaryrefslogtreecommitdiffstats
path: root/cli_ure/source/uno_bridge/cli_data.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /cli_ure/source/uno_bridge/cli_data.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cli_ure/source/uno_bridge/cli_data.cxx')
-rw-r--r--cli_ure/source/uno_bridge/cli_data.cxx1929
1 files changed, 1929 insertions, 0 deletions
diff --git a/cli_ure/source/uno_bridge/cli_data.cxx b/cli_ure/source/uno_bridge/cli_data.cxx
new file mode 100644
index 000000000..72b39df48
--- /dev/null
+++ b/cli_ure/source/uno_bridge/cli_data.cxx
@@ -0,0 +1,1929 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#include <ole2.h>
+
+#include <memory>
+
+#include "rtl/ustring.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "uno/sequence2.h"
+#include "typelib/typedescription.hxx"
+#include "cli_proxy.h"
+#include "cli_base.h"
+#include "cli_bridge.h"
+
+#using <cli_uretypes.dll>
+
+#undef VOID
+
+namespace sri = System::Runtime::InteropServices;
+namespace sr = System::Reflection;
+namespace st = System::Text;
+namespace ucss = unoidl::com::sun::star;
+
+
+namespace cli_uno
+{
+System::String^ mapUnoPolymorphicName(System::String^ unoName);
+OUString mapCliTypeName(System::String^ typeName);
+System::String^ mapCliPolymorphicName(System::String^ unoName);
+System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno);
+
+inline std::unique_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize )
+{
+ std::unique_ptr< rtl_mem > seq(
+ rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) );
+ uno_Sequence * p = (uno_Sequence *)seq.get();
+ p->nRefCount = 1;
+ p->nElements = nElements;
+ return seq;
+}
+
+System::Object^ Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const
+{
+ System::Object^ retVal= nullptr;
+ // get oid
+ rtl_uString * pOid = 0;
+ (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
+ OSL_ASSERT( 0 != pOid );
+ OUString oid(pOid, SAL_NO_ACQUIRE);
+
+ // see if the interface was already mapped
+ System::Type^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
+ System::String^ sOid= mapUnoString(oid.pData);
+
+ System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env );
+ try
+ {
+ retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType);
+ if (retVal)
+ {
+ // There is already a registered object. It can either be a proxy
+ // for the UNO object or a real cli object. In the first case we
+ // tell the proxy that it shall also represent the current UNO
+ // interface. If it already does that, then it does nothing
+ if (srr::RemotingServices::IsTransparentProxy(retVal))
+ {
+ UnoInterfaceProxy^ p = static_cast<UnoInterfaceProxy^>(
+ srr::RemotingServices::GetRealProxy(retVal));
+ p->addUnoInterface(pUnoI, pTD);
+ }
+ }
+ else
+ {
+ retVal = UnoInterfaceProxy::create(
+ (Bridge *) this, pUnoI, pTD, oid );
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
+ }
+
+ return retVal;
+}
+
+uno_Interface* Bridge::map_cli2uno(System::Object^ cliObj, typelib_TypeDescription *pTD) const
+{
+ uno_Interface* retIface = NULL;
+ // get oid from dot net environment
+ System::String^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
+ OUString ousOid = mapCliString(ds_oid);
+ // look if interface is already mapped
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ System::Threading::Monitor::Enter(Cli_environment::typeid);
+ try
+ {
+ m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
+ (typelib_InterfaceTypeDescription*) pTD);
+ if ( ! retIface)
+ {
+ retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
+ }
+ }
+ __finally
+ {
+ System::Threading::Monitor::Exit(Cli_environment::typeid);
+ }
+ }
+ return retIface;
+}
+
+inline System::Type^ loadCliType(rtl_uString * unoName)
+{
+ return loadCliType(mapUnoTypeName(unoName));
+}
+
+System::Type^ loadCliType(System::String ^ unoName)
+{
+ System::Type^ retVal= nullptr;
+ try
+ {
+ //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char>
+ //then we remove the type list, otherwise the type could not be loaded.
+ bool bIsPolymorphic = false;
+
+ System::String ^ loadName = unoName;
+ int index = unoName->IndexOf('<');
+ if (index != -1)
+ {
+ loadName = unoName->Substring(0, index);
+ bIsPolymorphic = true;
+ }
+ System::AppDomain^ currentDomain = System::AppDomain::CurrentDomain;
+ cli::array<sr::Assembly^>^ assems = currentDomain->GetAssemblies();
+ for (int i = 0; i < assems->Length; i++)
+ {
+ retVal = assems[i]->GetType(loadName, false);
+ if (retVal)
+ break;
+ }
+
+ if (retVal == nullptr)
+ {
+ System::String ^ msg = gcnew System::String("A type could not be loaded: ");
+ msg = System::String::Concat(msg, loadName);
+ throw BridgeRuntimeError(mapCliString(msg));
+ }
+
+ if (bIsPolymorphic)
+ {
+ retVal = uno::PolymorphicType::GetType(retVal, unoName);
+ }
+ }
+ catch( System::Exception ^ e)
+ {
+ OUString ouMessage(mapCliString(e->Message));
+ throw BridgeRuntimeError(ouMessage);
+ }
+ return retVal;
+}
+
+System::Type^ mapUnoType(typelib_TypeDescription const * pTD)
+{
+ return mapUnoType(pTD->pWeakRef);
+}
+
+System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD)
+{
+ System::Type ^ retVal = nullptr;
+ switch (pTD->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ retVal= void::typeid; break;
+ case typelib_TypeClass_CHAR:
+ retVal= System::Char::typeid; break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= System::Boolean::typeid; break;
+ case typelib_TypeClass_BYTE:
+ retVal= System::Byte::typeid; break;
+ case typelib_TypeClass_SHORT:
+ retVal= System::Int16::typeid; break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= System::UInt16::typeid; break;
+ case typelib_TypeClass_LONG:
+ retVal= System::Int32::typeid; break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= System::UInt32::typeid; break;
+ case typelib_TypeClass_HYPER:
+ retVal= System::Int64::typeid; break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= System::UInt64::typeid; break;
+ case typelib_TypeClass_FLOAT:
+ retVal= System::Single::typeid; break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= System::Double::typeid; break;
+ case typelib_TypeClass_STRING:
+ retVal= System::String::typeid; break;
+ case typelib_TypeClass_TYPE:
+ retVal= System::Type::typeid; break;
+ case typelib_TypeClass_ANY:
+ retVal= uno::Any::typeid; break;
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ retVal= loadCliType(pTD->pTypeName); break;
+ case typelib_TypeClass_INTERFACE:
+ {
+ //special handling for XInterface, since it does not exist in cli.
+ OUString usXInterface("com.sun.star.uno.XInterface");
+ if (usXInterface.equals(pTD->pTypeName))
+ retVal= System::Object::typeid;
+ else
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ css::uno::TypeDescription seqType(
+ const_cast<typelib_TypeDescriptionReference*>(pTD));
+ typelib_TypeDescriptionReference* pElementTDRef=
+ reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType;
+ switch (pElementTDRef->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArChar)); break;
+ case typelib_TypeClass_BOOLEAN:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArBoolean));
+ break;
+ case typelib_TypeClass_BYTE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArByte));
+ break;
+ case typelib_TypeClass_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt16));
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt16));
+ break;
+ case typelib_TypeClass_LONG:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt32));
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt32));
+ break;
+ case typelib_TypeClass_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt64));
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt64));
+ break;
+ case typelib_TypeClass_FLOAT:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArSingle));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArDouble));
+ break;
+ case typelib_TypeClass_STRING:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArString));
+ break;
+ case typelib_TypeClass_TYPE:
+ retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArType));
+ break;
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_INTERFACE:
+ case typelib_TypeClass_SEQUENCE:
+ {
+ retVal= loadCliType(pTD->pTypeName);
+ break;
+ }
+ default:
+ //All cases should be handled by the case statements above
+ OSL_ASSERT(0);
+ break;
+ }
+ break;
+ }
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+ return retVal;
+}
+
+/** Returns an acquired td.
+ */
+typelib_TypeDescriptionReference* mapCliType(System::Type^ cliType)
+{
+ typelib_TypeDescriptionReference* retVal= NULL;
+ if (cliType == nullptr)
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ return retVal;
+ }
+ //check for Enum first,
+ //because otherwise case System::TypeCode::Int32 applies
+ if (cliType->IsEnum)
+ {
+ OUString usTypeName= mapCliTypeName(cliType->FullName);
+ css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
+ retVal= unoType.getTypeLibType();
+ typelib_typedescriptionreference_acquire(retVal);
+ }
+ else
+ {
+ switch (System::Type::GetTypeCode(cliType))
+ {
+ case System::TypeCode::Boolean:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BOOLEAN );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Char:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_CHAR );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Byte:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_BYTE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Int64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt16:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_SHORT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt32:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_LONG );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::UInt64:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_UNSIGNED_HYPER );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Single:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_FLOAT );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::Double:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_DOUBLE );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ case System::TypeCode::String:
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_STRING );
+ typelib_typedescriptionreference_acquire( retVal );
+ break;
+ default:
+ break;
+ }
+ }
+ if (retVal == NULL)
+ {
+ System::String^ cliTypeName= cliType->FullName;
+ // Void
+ if (const_cast<System::String^>(Constants::sVoid)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_VOID );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Type
+ else if (const_cast<System::String^>(Constants::sType)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_TYPE );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ // Any
+ else if (const_cast<System::String^>(Constants::sAny)->Equals(
+ cliTypeName))
+ {
+ retVal = * typelib_static_type_getByTypeClass(
+ typelib_TypeClass_ANY );
+ typelib_typedescriptionreference_acquire( retVal );
+ }
+ //struct, interfaces, sequences
+ else
+ {
+ OUString usTypeName;
+ uno::PolymorphicType ^ poly = dynamic_cast<uno::PolymorphicType^>(cliType);
+ if (poly != nullptr)
+ usTypeName = mapCliTypeName( poly->PolymorphicName);
+ else
+ usTypeName = mapCliTypeName(cliTypeName);
+ typelib_TypeDescription* td = NULL;
+ typelib_typedescription_getByName(&td, usTypeName.pData);
+ if (td)
+ {
+ retVal = td->pWeakRef;
+ typelib_typedescriptionreference_acquire(retVal);
+ typelib_typedescription_release(td);
+ }
+ }
+ }
+ if (retVal == NULL)
+ {
+ throw BridgeRuntimeError("[cli_uno bridge] mapCliType():could not map type: " + mapCliString(cliType->FullName));
+ }
+ return retVal;
+}
+
+/**
+ Otherwise a leading "unoidl." is removed.
+ */
+System::String^ mapUnoTypeName(rtl_uString const * typeName)
+{
+ OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
+ st::StringBuilder^ buf= gcnew st::StringBuilder();
+ //determine if the type is a sequence and its dimensions
+ int dims= 0;
+ if (usUnoName[0] == '[')
+ {
+ sal_Int32 index= 1;
+ while (true)
+ {
+ if (usUnoName[index++] == ']')
+ dims++;
+ if (usUnoName[index++] != '[')
+ break;
+ }
+ usUnoName = usUnoName.copy(index - 1);
+ }
+ System::String ^ sUnoName = mapUnoString(usUnoName.pData);
+ if (sUnoName->Equals(const_cast<System::String^>(Constants::usBool)))
+ buf->Append(const_cast<System::String^>(Constants::sBoolean));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usChar)))
+ buf->Append(const_cast<System::String^>(Constants::sChar));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usByte)))
+ buf->Append(const_cast<System::String^>(Constants::sByte));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usShort)))
+ buf->Append(const_cast<System::String^>(Constants::sInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUShort)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt16));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usLong)))
+ buf->Append(const_cast<System::String^>(Constants::sInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usULong)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt32));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUHyper)))
+ buf->Append(const_cast<System::String^>(Constants::sUInt64));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usFloat)))
+ buf->Append(const_cast<System::String^>(Constants::sSingle));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usDouble)))
+ buf->Append(const_cast<System::String^>(Constants::sDouble));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usString)))
+ buf->Append(const_cast<System::String^>(Constants::sString));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usVoid)))
+ buf->Append(const_cast<System::String^>(Constants::sVoid));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usType)))
+ buf->Append(const_cast<System::String^>(Constants::sType));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usXInterface)))
+ buf->Append(const_cast<System::String^>(Constants::sObject));
+ else if (sUnoName->Equals(const_cast<System::String^>(Constants::usAny)))
+ {
+ buf->Append(const_cast<System::String^>(Constants::sAny));
+ }
+ else
+ {
+ //put "unoidl." at the beginning
+ buf->Append(const_cast<System::String^>(Constants::sUnoidl));
+ //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
+ System::String ^ sName = mapUnoPolymorphicName(sUnoName);
+ buf->Append(sName);
+ }
+ // append []
+ for (;dims--;)
+ buf->Append(const_cast<System::String^>(Constants::sBrackets));
+
+ return buf->ToString();
+}
+
+/** For example, there is a uno type
+ com.sun.star.Foo<char, long>.
+ The values in the type list
+ are uno types and are replaced by cli types, such as System.Char,
+ System.Int32, etc.
+ The prefix unoidl is not added.
+ */
+inline System::String^ mapUnoPolymorphicName(System::String^ unoName)
+{
+ return mapPolymorphicName(unoName, false);
+}
+
+/** For example, there is a type name such as
+ com.sun.star.Foo<System.Char, System.Int32>.
+ The values in the type list
+ are CLI types and are replaced by uno types, such as char,
+ long, etc.
+ The prefix unoidl remains.
+ */
+inline System::String^ mapCliPolymorphicName(System::String^ unoName)
+{
+ return mapPolymorphicName(unoName, true);
+}
+
+System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno)
+{
+ int index = unoName->IndexOf('<');
+ if (index == -1)
+ return unoName;
+
+ System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256);
+ builder->Append(unoName->Substring(0, index +1 ));
+
+ //Find the first occurrence of ','
+ //If the parameter is a polymorphic struct then we need to ignore everything
+ //between the brackets because it can also contain commas
+ //get the type list within < and >
+ int endIndex = unoName->Length - 1;
+ index++;
+ int cur = index;
+ int countParams = 0;
+ while (cur <= endIndex)
+ {
+ System::Char c = unoName[cur];
+ if (c == ',' || c == '>')
+ {
+ //insert a comma if needed
+ if (countParams != 0)
+ builder->Append(",");
+ countParams++;
+ System::String ^ sParam = unoName->Substring(index, cur - index);
+ //skip the comma
+ cur++;
+ //the index to the beginning of the next param
+ index = cur;
+ if (bCliToUno)
+ {
+ builder->Append(mapCliTypeName(sParam).getStr());
+ }
+ else
+ {
+ OUString s = mapCliString(sParam);
+ builder->Append(mapUnoTypeName(s.pData));
+ }
+ }
+ else if (c == '<')
+ {
+ cur++;
+ //continue until the matching '>'
+ int numNested = 0;
+ for (;;cur++)
+ {
+ System::Char curChar = unoName[cur];
+ if (curChar == '<')
+ {
+ numNested ++;
+ }
+ else if (curChar == '>')
+ {
+ if (numNested > 0)
+ numNested--;
+ else
+ break;
+ }
+ }
+ }
+ cur++;
+ }
+
+ builder->Append((System::Char) '>');
+ return builder->ToString();
+}
+
+OUString mapCliTypeName(System::String^ typeName)
+{
+ int dims= 0;
+ // Array? determine the "rank" (number of "[]")
+ // move from the rightmost end to the left, for example
+ // unoidl.PolymorphicStruct<System.Char[]>[]
+ // has only a "dimension" of 1
+ int cur = typeName->Length - 1;
+ bool bRightBracket = false;
+ while (cur >= 0)
+ {
+ System::Char c = typeName[cur];
+ if (c == ']')
+ {
+ bRightBracket = true;
+ }
+ else if (c == '[')
+ {
+ if (!bRightBracket)
+ throw BridgeRuntimeError(
+ "Typename is wrong. No matching brackets for sequence. Name is: " +
+ mapCliString(typeName));
+ bRightBracket = false;
+ dims ++;
+ }
+ else
+ {
+ if (bRightBracket)
+ throw BridgeRuntimeError(
+ "Typename is wrong. No matching brackets for sequence. Name is: " +
+ mapCliString(typeName));
+ break;
+ }
+ cur--;
+ }
+
+ if (bRightBracket || cur < 0)
+ throw BridgeRuntimeError(
+ "Typename is wrong. " +
+ mapCliString(typeName));
+
+ typeName = typeName->Substring(0, cur + 1);
+
+ System::Text::StringBuilder ^ buf = gcnew System::Text::StringBuilder(512);
+
+ //Put the "[]" at the beginning of the uno type name
+ for (;dims--;)
+ buf->Append(const_cast<System::String^>(Constants::usBrackets));
+
+ if (typeName->Equals(const_cast<System::String^>(Constants::sBoolean)))
+ buf->Append(const_cast<System::String^>(Constants::usBool));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sChar)))
+ buf->Append(const_cast<System::String^>(Constants::usChar));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sByte)))
+ buf->Append(const_cast<System::String^>(Constants::usByte));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt16)))
+ buf->Append(const_cast<System::String^>(Constants::usShort));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt16)))
+ buf->Append(const_cast<System::String^>(Constants::usUShort));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt32)))
+ buf->Append(const_cast<System::String^>(Constants::usLong));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt32)))
+ buf->Append(const_cast<System::String^>(Constants::usULong));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sInt64)))
+ buf->Append(const_cast<System::String^>(Constants::usHyper));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt64)))
+ buf->Append(const_cast<System::String^>(Constants::usUHyper));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sSingle)))
+ buf->Append(const_cast<System::String^>(Constants::usFloat));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sDouble)))
+ buf->Append(const_cast<System::String^>(Constants::usDouble));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sString)))
+ buf->Append(const_cast<System::String^>(Constants::usString));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sVoid)))
+ buf->Append(const_cast<System::String^>(Constants::usVoid));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sType)))
+ buf->Append(const_cast<System::String^>(Constants::usType));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sObject)))
+ buf->Append(const_cast<System::String^>(Constants::usXInterface));
+ else if (typeName->Equals(const_cast<System::String^>(Constants::sAny)))
+ buf->Append(const_cast<System::String^>(Constants::usAny));
+ else
+ {
+ System::String ^ sName = mapCliPolymorphicName(typeName);
+ int i= sName->IndexOf(L'.');
+ buf->Append(sName->Substring(i + 1));
+ }
+ return mapCliString(buf->ToString());
+}
+
+/** Maps uno types to dot net types.
+ * If uno_data is null then the type description is converted to System::Type
+ */
+inline System::String^ mapUnoString( rtl_uString const * data)
+{
+ OSL_ASSERT(data);
+ return gcnew System::String((__wchar_t*) data->buffer, 0, data->length);
+}
+
+OUString mapCliString(System::String ^ data)
+{
+
+ if (data != nullptr)
+ {
+ static_assert(sizeof(wchar_t) == sizeof(sal_Unicode), "char mismatch");
+ pin_ptr<wchar_t const> pdata= PtrToStringChars(data);
+ return OUString(
+ reinterpret_cast<sal_Unicode const *>(pdata),
+ const_cast<System::String^>(data)->Length);
+ }
+ else
+ {
+ return OUString();
+ }
+}
+
+// ToDo convert cli types to expected types, e.g a long to a short where the uno type
+// is a sal_Int16. This could be necessary if a scripting language (typeless) is used
+// @param assign the uno_data has to be destructed (in/out args)
+void Bridge::map_to_uno(void * uno_data, System::Object^ cli_data,
+ typelib_TypeDescriptionReference * type,
+ bool assign) const
+{
+ try{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ break;
+ case typelib_TypeClass_CHAR:
+ {
+ System::Char aChar= *safe_cast<System::Char^>(cli_data);
+ *(sal_Unicode*) uno_data= aChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ System::Boolean aBool= *safe_cast<System::Boolean^>(cli_data);
+ *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ System::Byte aByte= *safe_cast<System::Byte^>(cli_data);
+ *(sal_Int8*) uno_data= aByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ System::Int16 aShort= *safe_cast<System::Int16^>(cli_data);
+ *(sal_Int16*) uno_data= aShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ System::UInt16 aUShort= *safe_cast<System::UInt16^>(cli_data);
+ *(sal_uInt16*) uno_data= aUShort;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ System::Int32 aLong= *safe_cast<System::Int32^>(cli_data);
+ *(sal_Int32*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ System::UInt32 aULong= *safe_cast<System::UInt32^>(cli_data);
+ *(sal_uInt32*) uno_data= aULong;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ System::Int64 aHyper= *safe_cast<System::Int64^>(cli_data);
+ *(sal_Int64*) uno_data= aHyper;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ System::UInt64 aLong= *safe_cast<System::UInt64^>(cli_data);
+ *(sal_uInt64*) uno_data= aLong;
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ System::Single aFloat= *safe_cast<System::Single^>(cli_data);
+ *(float*) uno_data= aFloat;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ System::Double aDouble= *safe_cast<System::Double^>(cli_data);
+ *(double*) uno_data= aDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ if (assign && *(rtl_uString**) uno_data)
+ rtl_uString_release(*(rtl_uString**) uno_data);
+
+ *(rtl_uString **)uno_data = 0;
+ if (cli_data == nullptr)
+ {
+ rtl_uString_new((rtl_uString**) uno_data);
+ }
+ else
+ {
+ System::String ^s= safe_cast<System::String^>(cli_data);
+ pin_ptr<const wchar_t> pdata= PtrToStringChars(s);
+ rtl_uString_newFromStr_WithLength(
+ reinterpret_cast<rtl_uString **>(uno_data),
+ reinterpret_cast<sal_Unicode const *>(pdata), s->Length);
+ }
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ typelib_TypeDescriptionReference* td= mapCliType(safe_cast<System::Type^>(
+ cli_data));
+ if (assign)
+ {
+ typelib_typedescriptionreference_release(
+ *(typelib_TypeDescriptionReference **)uno_data );
+ }
+ *(typelib_TypeDescriptionReference **)uno_data = td;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any * pAny = (uno_Any *)uno_data;
+ if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any
+ {
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+ uno_any_construct( pAny, 0, 0, 0 );
+ break;
+ }
+ uno::Any aAny= *safe_cast<uno::Any^>(cli_data);
+ css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
+
+ if (assign)
+ uno_any_destruct( pAny, 0 );
+
+ try
+ {
+ switch (value_td.getTypeClass())
+ {
+ case css::uno::TypeClass_VOID:
+ pAny->pData = &pAny->pReserved;
+ break;
+ case css::uno::TypeClass_CHAR:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Unicode*) &pAny->pReserved = *safe_cast<System::Char^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_BOOLEAN:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Bool *) &pAny->pReserved = *safe_cast<System::Boolean^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_BYTE:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int8*) &pAny->pReserved = *safe_cast<System::Byte^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int16*) &pAny->pReserved = *safe_cast<System::Int16^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_UNSIGNED_SHORT:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt16*) &pAny->pReserved = *safe_cast<System::UInt16^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int32*) &pAny->pReserved = *safe_cast<System::Int32^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_UNSIGNED_LONG:
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt32*) &pAny->pReserved = *safe_cast<System::UInt32^>(aAny.Value);
+ break;
+ case css::uno::TypeClass_HYPER:
+ if (sizeof (sal_Int64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_Int64*) &pAny->pReserved = *safe_cast<System::Int64^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
+ *(sal_Int64 *) mem.get()= *safe_cast<System::Int64^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_UNSIGNED_HYPER:
+ if (sizeof (sal_uInt64) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(sal_uInt64*) &pAny->pReserved = *safe_cast<System::UInt64^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
+ *(sal_uInt64 *) mem.get()= *safe_cast<System::UInt64^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_FLOAT:
+ if (sizeof (float) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(float*) &pAny->pReserved = *safe_cast<System::Single^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
+ *(float*) mem.get() = *safe_cast<System::Single^>(aAny.Value);
+ pAny->pData = mem.release();
+ }
+ break;
+ case css::uno::TypeClass_DOUBLE:
+ if (sizeof (double) <= sizeof (void *))
+ {
+ pAny->pData = &pAny->pReserved;
+ *(double*) &pAny->pReserved= *safe_cast<System::Double^>(aAny.Value);
+ }
+ else
+ {
+ std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
+ *(double*) mem.get()= *safe_cast<System::Double^>(aAny.Value);
+ pAny->pData= mem.release();
+ }
+ break;
+ case css::uno::TypeClass_STRING: // anies often contain strings; copy string directly
+ {
+ pAny->pData= &pAny->pReserved;
+ OUString _s = mapCliString(static_cast<System::String^>(aAny.Value));
+ pAny->pReserved= _s.pData;
+ rtl_uString_acquire(_s.pData);
+ break;
+ }
+ case css::uno::TypeClass_TYPE:
+ case css::uno::TypeClass_ENUM: //ToDo copy enum direct
+ case css::uno::TypeClass_SEQUENCE:
+ case css::uno::TypeClass_INTERFACE:
+ pAny->pData = &pAny->pReserved;
+ pAny->pReserved = 0;
+ map_to_uno(
+ &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ break;
+ case css::uno::TypeClass_STRUCT:
+ case css::uno::TypeClass_EXCEPTION:
+ {
+ css::uno::Type anyType(value_td);
+ typelib_TypeDescription* td= NULL;
+ anyType.getDescription(&td);
+ std::unique_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
+ typelib_typedescription_release(td);
+ map_to_uno(
+ mem.get(), aAny.Value, value_td.getTypeLibType(),
+ false /* no assign */);
+ pAny->pData = mem.release();
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + value_td.getTypeName() + "] unsupported value type of any!");
+ }
+ }
+ }
+ catch(System::InvalidCastException^ )
+ {
+// ToDo check this
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ OUString str = "[map_to_uno():Any" + value_td.getTypeName() + "]The Any type " + value_td.getTypeName() + " does not correspond to its value type: ";
+ if(aAny.Value != nullptr)
+ {
+ css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
+ str += td.getTypeName();
+ }
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw BridgeRuntimeError(str);
+ }
+ catch (BridgeRuntimeError& )
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+ catch (...)
+ {
+ if (assign)
+ uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
+ throw;
+ }
+
+ pAny->pType = value_td.getTypeLibType();
+ typelib_typedescriptionreference_acquire(pAny->pType);
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ // InvalidCastException is caught at the end of this method
+ System::Int32 aEnum= System::Convert::ToInt32((cli_data));
+ *(sal_Int32*) uno_data = aEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ css::uno::TypeDescription td(type);
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription*) td.get();
+
+ typelib_StructTypeDescription * struct_td = NULL;
+ if (type->eTypeClass == typelib_TypeClass_STRUCT)
+ struct_td = (typelib_StructTypeDescription*) td.get();
+
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+ sal_Int32 nMembers = comp_td->nMembers;
+ boolean bException= false;
+ System::Type^ cliType = nullptr;
+ if (cli_data)
+ cliType = cli_data->GetType();
+
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ map_to_uno(
+ uno_data, cli_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
+ assign);
+ }
+ sal_Int32 nPos = 0;
+ try
+ {
+ OUString usUnoException("com.sun.star.uno.Exception");
+ for (; nPos < nMembers; ++nPos)
+ {
+ typelib_TypeDescriptionReference * member_type= comp_td->ppTypeRefs[nPos];
+ System::Object^ val= nullptr;
+ if (cli_data != nullptr)
+ {
+ sr::FieldInfo^ aField= cliType->GetField(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ // special case for Exception.Message property
+ // The com.sun.star.uno.Exception.Message field is mapped to the
+ // System.Exception property. Type.GetField("Message") returns null
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {// get Exception.Message property
+ OUString usMessageMember("Message");
+ if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
+ {
+ sr::PropertyInfo^ pi= cliType->GetProperty(
+ mapUnoString(comp_td->ppMemberNames[nPos]));
+ val= pi->GetValue(cli_data, nullptr);
+ }
+ else
+ {
+ throw BridgeRuntimeError("[map_to_uno(): Member: " + OUString::unacquired(&comp_td->ppMemberNames[nPos]));
+ }
+ }
+ else
+ {
+ val= aField->GetValue(cli_data);
+ }
+ }
+ void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
+ //When using polymorphic structs then the parameterized members can be null.
+ //Then we set a default value.
+ bool bDefault = (struct_td != NULL
+ && struct_td->pParameterizedTypes != NULL
+ && struct_td->pParameterizedTypes[nPos] == sal_True
+ && val == nullptr)
+ || cli_data == nullptr;
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ if (bDefault)
+ *(sal_Unicode*) p = 0;
+ else
+ *(sal_Unicode*) p = *safe_cast<System::Char^>(val);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ if (bDefault)
+ *(sal_Bool*) p = sal_False;
+ else
+ *(sal_Bool*) p = *safe_cast<System::Boolean^>(val);
+ break;
+ case typelib_TypeClass_BYTE:
+ if (bDefault)
+ *(sal_Int8*) p = 0;
+ else
+ *(sal_Int8*) p = *safe_cast<System::Byte^>(val);
+ break;
+ case typelib_TypeClass_SHORT:
+ if (bDefault)
+ *(sal_Int16*) p = 0;
+ else
+ *(sal_Int16*) p = *safe_cast<System::Int16^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ if (bDefault)
+ *(sal_uInt16*) p = 0;
+ else
+ *(sal_uInt16*) p = *safe_cast<System::UInt16^>(val);
+ break;
+ case typelib_TypeClass_LONG:
+ if (bDefault)
+ *(sal_Int32*) p = 0;
+ else
+ *(sal_Int32*) p = *safe_cast<System::Int32^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ if (bDefault)
+ *(sal_uInt32*) p = 0;
+ else
+ *(sal_uInt32*) p = *safe_cast<System::UInt32^>(val);
+ break;
+ case typelib_TypeClass_HYPER:
+ if (bDefault)
+ *(sal_Int64*) p = 0;
+ else
+ *(sal_Int64*) p = *safe_cast<System::Int64^>(val);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (bDefault)
+ *(sal_uInt64*) p = 0;
+ else
+ *(sal_uInt64*) p= *safe_cast<System::UInt64^>(val);
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (bDefault)
+ *(float*) p = 0.;
+ else
+ *(float*) p = *safe_cast<System::Single^>(val);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (bDefault)
+ *(double*) p = 0.;
+ else
+ *(double*) p = *safe_cast<System::Double^>(val);
+ break;
+ default:
+ { // ToDo enum, should be converted here
+ map_to_uno(p, val, member_type, assign);
+ break;
+ }
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ bException= true;
+ OUString str = "[map_to_uno():";
+ if (cliType)
+ {
+ str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]) + " ";
+ }
+ str += e.m_message;
+ throw BridgeRuntimeError(str);
+ }
+ catch (System::InvalidCastException^ )
+ {
+ bException= true;
+ OUString str = "[map_to_uno():";
+ if (cliType)
+ {
+ str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]);
+ }
+ str += "] Value has not the required type.";
+ throw BridgeRuntimeError(str);
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ bException= true;
+ throw;
+ }
+ __finally
+ {
+ if (bException && !assign) // if assign then caller cleans up
+ {
+ // cleanup the members which we have converted so far
+ for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
+ {
+ uno_type_destructData(
+ uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
+ }
+ if (0 != comp_td->pBaseTypeDescription)
+ {
+ uno_destructData(
+ uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
+ }
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ std::unique_ptr< rtl_mem > seq;
+
+ System::Array^ ar = nullptr;
+ if (cli_data != nullptr)
+ {
+ ar = safe_cast<System::Array^>(cli_data);
+ sal_Int32 nElements = ar->GetLength(0);
+
+ try
+ {
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ seq = seq_allocate(nElements, sizeof (sal_Unicode));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ seq = seq_allocate(nElements, sizeof (sal_Bool));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_BYTE:
+ seq = seq_allocate( nElements, sizeof (sal_Int8) );
+ sri::Marshal::Copy(safe_cast<cli::array<System::Byte>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_SHORT:
+ seq = seq_allocate(nElements, sizeof (sal_Int16));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int16>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ seq = seq_allocate( nElements, sizeof (sal_uInt16) );
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int16>^>(
+ safe_cast<cli::array<System::UInt16>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_LONG:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int32>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ seq = seq_allocate( nElements, sizeof (sal_uInt32) );
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int32>^>(
+ safe_cast<cli::array<System::UInt32>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_Int64));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Int64>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ seq = seq_allocate(nElements, sizeof (sal_uInt64));
+ sri::Marshal::Copy(dynamic_cast<cli::array<System::Int64>^>(
+ safe_cast<cli::array<System::UInt64>^>(cli_data)), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_FLOAT:
+ seq = seq_allocate(nElements, sizeof (float));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Single>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ seq = seq_allocate(nElements, sizeof (double));
+ sri::Marshal::Copy(safe_cast<cli::array<System::Double>^>(cli_data), 0,
+ IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ seq = seq_allocate(nElements, sizeof (rtl_uString*));
+ cli::array<System::String^>^ arStr= safe_cast<cli::array<System::String^>^>(cli_data);
+ for (int i= 0; i < nElements; i++)
+ {
+ pin_ptr<const wchar_t> pdata= PtrToStringChars(arStr[i]);
+ rtl_uString** pStr= & ((rtl_uString**) &
+ ((uno_Sequence*) seq.get())->elements)[i];
+ *pStr= NULL;
+ rtl_uString_newFromStr_WithLength(
+ pStr,
+ reinterpret_cast<sal_Unicode const *>(pdata),
+ arStr[i]->Length);
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ seq = seq_allocate(nElements, sizeof (sal_Int32));
+ for (int i= 0; i < nElements; i++)
+ {
+ ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
+ System::Convert::ToInt32(ar->GetValue(i));
+ }
+ break;
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ seq = seq_allocate( nElements, element_td.get()->nSize );
+
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
+ {
+ try
+ {
+ void * p= ((uno_Sequence *) seq.get())->elements +
+ (nPos * element_td.get()->nSize);
+ System::Object^ elemData= safe_cast<System::Array^>(cli_data)->GetValue(System::Int32(nPos));
+ map_to_uno(
+ p, elemData, element_td.get()->pWeakRef,
+ false /* no assign */);
+ }
+ catch (...)
+ {
+ // cleanup
+ for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
+ {
+ void * p =
+ ((uno_Sequence *)seq.get())->elements +
+ (nCleanPos * element_td.get()->nSize);
+ uno_destructData( p, element_td.get(), 0 );
+ }
+ throw;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) +
+ "] unsupported sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ }
+ }
+ catch (BridgeRuntimeError& e)
+ {
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] conversion failed\n " + e.m_message);
+ }
+ catch (System::InvalidCastException^ )
+ {
+ // Ok, checked
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName) +
+ "] could not convert sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+ __finally
+ {
+ if (assign)
+ uno_destructData( uno_data, td.get(), 0 );
+ }
+ }
+ else
+ {
+ seq = seq_allocate(0, sizeof (sal_Int32));
+ }
+ *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ if (assign)
+ {
+ uno_Interface * p = *(uno_Interface **)uno_data;
+ if (0 != p)
+ (*p->release)( p );
+ }
+ if (nullptr == cli_data) // null-ref
+ {
+ *(uno_Interface **)uno_data = 0;
+ }
+ else
+ {
+ TypeDescr td( type );
+ uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
+ *(uno_Interface **)uno_data = pUnoI;
+ }
+ break;
+ }
+ default:
+ {
+ //ToDo check
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
+ }
+ }
+ }
+ // BridgeRuntimeError are allowed to be thrown
+ catch (System::InvalidCastException^ )
+ {
+ //ToDo check
+ throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] could not convert type!");
+ }
+ catch (System::NullReferenceException ^ e)
+ {
+ throw BridgeRuntimeError("[map_to_uno()] Illegal null reference passed!\n" + mapCliString(e->StackTrace));
+ }
+ catch (BridgeRuntimeError& )
+ {
+ throw;
+ }
+ catch (...)
+ {
+ OSL_ASSERT(0);
+ throw;
+ }
+}
+
+/**
+ @param info
+ The expected target type. Currently info is provided when this method is called
+ to convert the in/out and out parameters of a call from cli to uno. Then info
+ is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
+ @param bDontCreateObj
+ false - a new object is created which holds the mapped uno value and is assigned to
+ cli_data.
+ true - cli_data already contains the newly constructed object. This is the case if
+ a struct is converted then on the first call to map_to_cli the new object is created.
+ If the struct inherits another struct then this function is called recursively while the
+ newly created object is passed in cli_data.
+ */
+void Bridge::map_to_cli(
+ System::Object^ *cli_data, void const * uno_data,
+ typelib_TypeDescriptionReference * type, System::Type^ info,
+ bool bDontCreateObj) const
+{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ *cli_data= *(__wchar_t const*)uno_data;
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ *cli_data = (*(bool const*)uno_data) == sal_True;
+ break;
+ case typelib_TypeClass_BYTE:
+ *cli_data = *(unsigned char const*) uno_data;
+ break;
+ case typelib_TypeClass_SHORT:
+ *cli_data= *(short const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ *cli_data= *(unsigned short const*) uno_data;
+ break;
+ case typelib_TypeClass_LONG:
+ *cli_data= *(int const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ *cli_data= *(unsigned int const*) uno_data;
+ break;
+ case typelib_TypeClass_HYPER:
+ *cli_data= *(__int64 const*) uno_data;
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ *cli_data= *(unsigned __int64 const*) uno_data;
+ break;
+ case typelib_TypeClass_FLOAT:
+ *cli_data= *(float const*) uno_data;
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *cli_data= *(double const*) uno_data;
+ break;
+ case typelib_TypeClass_STRING:
+ {
+ rtl_uString const* sVal= NULL;
+ sVal= *(rtl_uString* const*) uno_data;
+ *cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length);
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ uno_Any const * pAny = (uno_Any const *)uno_data;
+ if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
+ {
+ System::Object^ objCli= nullptr;
+ map_to_cli(
+ &objCli, pAny->pData, pAny->pType, nullptr,
+ false);
+
+ uno::Any anyVal(mapUnoType(pAny->pType), objCli);
+ *cli_data= anyVal;
+ }
+ else
+ { // void any
+ *cli_data= uno::Any::VOID;
+ }
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ if (info != nullptr)
+ {
+ OSL_ASSERT(info->IsByRef);
+ info= info->GetElementType();
+ *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
+ }
+ else
+ *cli_data= System::Enum::ToObject(
+ mapUnoType(type), *(System::Int32*) uno_data);
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr td( type );
+ typelib_CompoundTypeDescription * comp_td =
+ (typelib_CompoundTypeDescription *) td.get();
+ if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
+ ::typelib_typedescription_complete(
+ (typelib_TypeDescription**) & comp_td );
+
+
+ //create the type
+ System::Type^ cliType= loadCliType(td.get()->pTypeName);
+ //detect if we recursively convert inherited structures
+ //If this point is reached because of a recursive call during covering a
+ //struct then we must not create a new object rather we use the one in
+ // cli_data argument.
+ System::Object^ cliObj;
+ if (bDontCreateObj)
+ cliObj = *cli_data; // recursive call
+ else
+ {
+ //Special handling for Exception conversion. We must call constructor System::Exception
+ //to pass the message string
+ if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType))
+ {
+ //We need to get the Message field. Therefore we must obtain the offset from
+ //the typedescription. The base interface of all exceptions is
+ //com::sun::star::uno::Exception which contains the message
+ typelib_CompoundTypeDescription* pCTD = comp_td;
+ while (pCTD->pBaseTypeDescription)
+ pCTD = pCTD->pBaseTypeDescription;
+ int nPos = -1;
+
+ OUString usMessageMember("Message");
+ for (int i = 0; i < pCTD->nMembers; i ++)
+ {
+ if (usMessageMember.equals(pCTD->ppMemberNames[i]))
+ {
+ nPos = i;
+ break;
+ }
+ }
+ OSL_ASSERT (nPos != -1);
+ int offset = pCTD->pMemberOffsets[nPos];
+ //With the offset within the exception we can get the message string
+ System::String^ sMessage = mapUnoString(*(rtl_uString**)
+ ((char*) uno_data + offset));
+ //We need to find a constructor for the exception that takes the message string
+ //We assume that the first argument is the message string
+ cli::array<sr::ConstructorInfo^>^ arCtorInfo = cliType->GetConstructors();
+ sr::ConstructorInfo^ ctorInfo = nullptr;
+ int numCtors = arCtorInfo->Length;
+ //Constructor must at least have 2 params for the base
+ //unoidl.com.sun.star.uno.Exception (String, Object);
+ cli::array<sr::ParameterInfo^>^ arParamInfo;
+ for (int i = 0; i < numCtors; i++)
+ {
+ arParamInfo = arCtorInfo[i]->GetParameters();
+ if (arParamInfo->Length < 2)
+ continue;
+ ctorInfo = arCtorInfo[i];
+ break;
+ }
+ OSL_ASSERT(arParamInfo[0]->ParameterType->Equals(System::String::typeid)
+ && arParamInfo[1]->ParameterType->Equals(System::Object::typeid)
+ && arParamInfo[0]->Position == 0
+ && arParamInfo[1]->Position == 1);
+ //Prepare parameters for constructor
+ int numArgs = arParamInfo->Length;
+ cli::array<System::Object^>^ args = gcnew cli::array<System::Object^>(numArgs);
+ //only initialize the first argument with the message
+ args[0] = sMessage;
+ cliObj = ctorInfo->Invoke(args);
+ }
+ else
+ cliObj = System::Activator::CreateInstance(cliType);
+ }
+ sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
+
+ if (comp_td->pBaseTypeDescription)
+ {
+ //convert inherited struct
+ //cliObj is passed inout (args in_param, out_param are true), hence the passed
+ // cliObj is used by the callee instead of a newly created struct
+ map_to_cli(
+ &cliObj, uno_data,
+ ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, nullptr,
+ true);
+ }
+ OUString usUnoException("com.sun.star.uno.Exception");
+ for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
+ {
+ typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
+ System::String^ sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
+ sr::FieldInfo^ aField= cliType->GetField(sMemberName);
+ // special case for Exception.Message. The field has already been
+ // set while constructing cli object
+ if ( ! aField && usUnoException.equals(td.get()->pTypeName))
+ {
+ continue;
+ }
+ void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
+ switch (member_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ aField->SetValue(cliObj, *(System::Char*) p);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ aField->SetValue(cliObj, *(System::Boolean*) p);
+ break;
+ case typelib_TypeClass_BYTE:
+ aField->SetValue(cliObj, *(System::Byte*) p);
+ break;
+ case typelib_TypeClass_SHORT:
+ aField->SetValue(cliObj, *(System::Int16*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ aField->SetValue(cliObj, *(System::UInt16*) p);
+ break;
+ case typelib_TypeClass_LONG:
+ aField->SetValue(cliObj, *(System::Int32*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ aField->SetValue(cliObj, *(System::UInt32*) p);
+ break;
+ case typelib_TypeClass_HYPER:
+ aField->SetValue(cliObj, *(System::Int64*) p);
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ aField->SetValue(cliObj, *(System::UInt64*) p);
+ break;
+ case typelib_TypeClass_FLOAT:
+ aField->SetValue(cliObj, *(System::Single*) p);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ aField->SetValue(cliObj, *(System::Double*) p);
+ break;
+ default:
+ {
+ System::Object^ cli_val;
+ map_to_cli(
+ &cli_val, p, member_type, nullptr,
+ false);
+ aField->SetValue(cliObj, cli_val);
+ break;
+ }
+ }
+ }
+ *cli_data= cliObj;
+ break;
+ }
+ case typelib_TypeClass_SEQUENCE:
+ {
+ sal_Int32 nElements;
+ uno_Sequence const * seq = 0;
+ seq = *(uno_Sequence * const *)uno_data;
+ nElements = seq->nElements;
+
+ TypeDescr td( type );
+ typelib_TypeDescriptionReference * element_type =
+ ((typelib_IndirectTypeDescription *)td.get())->pType;
+
+ switch (element_type->eTypeClass)
+ {
+ case typelib_TypeClass_CHAR:
+ {
+ cli::array<System::Char>^ arChar= gcnew cli::array<System::Char>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arChar, 0, nElements);
+ *cli_data= arChar;
+ break;
+ }
+ case typelib_TypeClass_BOOLEAN:
+ {
+ cli::array<System::Byte>^ arBool= gcnew cli::array<System::Byte>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arBool, 0, nElements);
+ *cli_data= dynamic_cast<cli::array<System::Boolean>^>(arBool);
+ break;
+ }
+ case typelib_TypeClass_BYTE:
+ {
+ cli::array<System::Byte>^ arByte= gcnew cli::array<System::Byte>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arByte, 0, nElements);
+ *cli_data= arByte;
+ break;
+ }
+ case typelib_TypeClass_SHORT:
+ {
+ cli::array<System::Int16>^ arShort= gcnew cli::array<System::Int16>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arShort, 0, nElements);
+ *cli_data= arShort;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ {
+ cli::array<System::UInt16>^ arUInt16= gcnew cli::array<System::UInt16>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int16>^>(arUInt16),
+ 0, nElements);
+ *cli_data= arUInt16;
+ break;
+ }
+ case typelib_TypeClass_LONG:
+ {
+ cli::array<System::Int32>^ arInt32= gcnew cli::array<System::Int32>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt32, 0, nElements);
+ *cli_data= arInt32;
+ break;
+ }
+ case typelib_TypeClass_UNSIGNED_LONG:
+ {
+ cli::array<System::UInt32>^ arUInt32= gcnew cli::array<System::UInt32>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int32>^>(arUInt32),
+ 0, nElements);
+ *cli_data= arUInt32;
+ break;
+ }
+ case typelib_TypeClass_HYPER:
+ {
+ cli::array<System::Int64>^ arInt64= gcnew cli::array<System::Int64>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt64, 0, nElements);
+ *cli_data= arInt64;
+ break;
+ }
+ //FIXME: Marshal::Copy of UInt64?
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ {
+ cli::array<System::IntPtr>^ arUInt64= gcnew cli::array<System::IntPtr>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arUInt64, 0, nElements);
+ *cli_data= dynamic_cast<cli::array<System::UInt64>^>(arUInt64);
+ break;
+ }
+ case typelib_TypeClass_FLOAT:
+ {
+ cli::array<System::Single>^ arSingle= gcnew cli::array<System::Single>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arSingle, 0, nElements);
+ *cli_data= arSingle;
+ break;
+ }
+ case typelib_TypeClass_DOUBLE:
+ {
+ cli::array<System::Double>^ arDouble= gcnew cli::array<System::Double>(nElements);
+ sri::Marshal::Copy( IntPtr((void*) &seq->elements), arDouble, 0, nElements);
+ *cli_data= arDouble;
+ break;
+ }
+ case typelib_TypeClass_STRING:
+ {
+ cli::array<System::String^>^ arString= gcnew cli::array<System::String^>(nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
+ arString[i]= gcnew System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
+ }
+ *cli_data= arString;
+ break;
+ }
+ case typelib_TypeClass_TYPE:
+ {
+ cli::array<System::Type^>^ arType= gcnew cli::array<System::Type^>(nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ arType[i]=
+ mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
+ }
+ *cli_data= arType;
+ break;
+ }
+ case typelib_TypeClass_ANY:
+ {
+ cli::array<uno::Any>^ arCli= gcnew cli::array<uno::Any>(nElements);
+ uno_Any const * p = (uno_Any const *)seq->elements;
+ for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ cli_obj = nullptr;
+ map_to_cli(
+ &cli_obj, &p[ nPos ], element_type, nullptr, false);
+ arCli[nPos]= *safe_cast<uno::Any^>(cli_obj);
+ }
+ *cli_data= arCli;
+ break;
+ }
+ case typelib_TypeClass_ENUM:
+ {
+ //get the Enum type
+ System::Type^ enumType= nullptr;
+ if (info != nullptr)
+ {
+ //info is EnumType[]&, remove &
+ OSL_ASSERT(info->IsByRef);
+ enumType = info->GetElementType();
+ //enumType is EnumType[], remove []
+ enumType = enumType->GetElementType();
+ }
+ else
+ enumType= mapUnoType(element_type);
+
+ System::Array^ arEnum = System::Array::CreateInstance(
+ enumType, nElements);
+ for (int i= 0; i < nElements; i++)
+ {
+ arEnum->SetValue(System::Enum::ToObject(enumType,
+ System::Int32(((sal_Int32*) seq->elements)[i])), i);
+ }
+ *cli_data = arEnum;
+ break;
+ }
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ TypeDescr element_td( element_type );
+ System::Array^ ar= System::Array::CreateInstance(
+ mapUnoType(element_type),nElements);
+ if (0 < nElements)
+ {
+ // ToDo check this
+ char * p = (char *) &seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, nullptr, false);
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+// ToDo, verify
+ case typelib_TypeClass_SEQUENCE:
+ {
+ System::Array ^ar= System::Array::CreateInstance(
+ mapUnoType(element_type), nElements);
+ if (0 < nElements)
+ {
+ TypeDescr element_td( element_type );
+ uno_Sequence ** elements = (uno_Sequence**) seq->elements;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, &elements[nPos], element_type, nullptr, false);
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ }
+ *cli_data = ar;
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ TypeDescr element_td( element_type );
+ System::Type ^ ifaceType= mapUnoType(element_type);
+ System::Array^ ar= System::Array::CreateInstance(ifaceType, nElements);
+
+ char * p = (char *)seq->elements;
+ sal_Int32 nSize = element_td.get()->nSize;
+ for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
+ {
+ System::Object^ val;
+ map_to_cli(
+ &val, p + (nSize * nPos), element_type, nullptr, false);
+
+ ar->SetValue(val, System::Int32(nPos));
+ }
+ *cli_data= ar;
+ break;
+ }
+ default:
+ {
+ throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) +
+ "] unsupported element type: " + OUString::unacquired( &element_type->pTypeName ));
+ }
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE:
+ {
+ uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
+ if (0 != pUnoI)
+ {
+ TypeDescr td( type );
+ *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
+ typelib_InterfaceTypeDescription*>(td.get())) ;
+ }
+ else
+ *cli_data= nullptr;
+ break;
+ }
+ default:
+ {
+ //ToDo check this exception. The String is probably crippled
+ throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
+ }
+ } //switch
+} // method
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */