Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_data.cxx
blob72b39df4884f43b024eaa69dc5ae216983a56b14
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #if !defined WIN32_LEAN_AND_MEAN
21 # define WIN32_LEAN_AND_MEAN
22 #endif
23 #include "windows.h"
24 #include <ole2.h>
26 #include <memory>
28 #include "rtl/ustring.hxx"
29 #include "rtl/ustrbuf.hxx"
30 #include "uno/sequence2.h"
31 #include "typelib/typedescription.hxx"
32 #include "cli_proxy.h"
33 #include "cli_base.h"
34 #include "cli_bridge.h"
36 #using <cli_uretypes.dll>
38 #undef VOID
40 namespace sri = System::Runtime::InteropServices;
41 namespace sr = System::Reflection;
42 namespace st = System::Text;
43 namespace ucss = unoidl::com::sun::star;
46 namespace cli_uno
48 System::String^ mapUnoPolymorphicName(System::String^ unoName);
49 OUString mapCliTypeName(System::String^ typeName);
50 System::String^ mapCliPolymorphicName(System::String^ unoName);
51 System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno);
53 inline std::unique_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize )
55 std::unique_ptr< rtl_mem > seq(
56 rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) );
57 uno_Sequence * p = (uno_Sequence *)seq.get();
58 p->nRefCount = 1;
59 p->nElements = nElements;
60 return seq;
63 System::Object^ Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const
65 System::Object^ retVal= nullptr;
66 // get oid
67 rtl_uString * pOid = 0;
68 (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
69 OSL_ASSERT( 0 != pOid );
70 OUString oid(pOid, SAL_NO_ACQUIRE);
72 // see if the interface was already mapped
73 System::Type^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
74 System::String^ sOid= mapUnoString(oid.pData);
76 System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env );
77 try
79 retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType);
80 if (retVal)
82 // There is already a registered object. It can either be a proxy
83 // for the UNO object or a real cli object. In the first case we
84 // tell the proxy that it shall also represent the current UNO
85 // interface. If it already does that, then it does nothing
86 if (srr::RemotingServices::IsTransparentProxy(retVal))
88 UnoInterfaceProxy^ p = static_cast<UnoInterfaceProxy^>(
89 srr::RemotingServices::GetRealProxy(retVal));
90 p->addUnoInterface(pUnoI, pTD);
93 else
95 retVal = UnoInterfaceProxy::create(
96 (Bridge *) this, pUnoI, pTD, oid );
99 __finally
101 System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
104 return retVal;
107 uno_Interface* Bridge::map_cli2uno(System::Object^ cliObj, typelib_TypeDescription *pTD) const
109 uno_Interface* retIface = NULL;
110 // get oid from dot net environment
111 System::String^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
112 OUString ousOid = mapCliString(ds_oid);
113 // look if interface is already mapped
114 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
115 (typelib_InterfaceTypeDescription*) pTD);
116 if ( ! retIface)
118 System::Threading::Monitor::Enter(Cli_environment::typeid);
121 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
122 (typelib_InterfaceTypeDescription*) pTD);
123 if ( ! retIface)
125 retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
128 __finally
130 System::Threading::Monitor::Exit(Cli_environment::typeid);
133 return retIface;
136 inline System::Type^ loadCliType(rtl_uString * unoName)
138 return loadCliType(mapUnoTypeName(unoName));
141 System::Type^ loadCliType(System::String ^ unoName)
143 System::Type^ retVal= nullptr;
146 //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char>
147 //then we remove the type list, otherwise the type could not be loaded.
148 bool bIsPolymorphic = false;
150 System::String ^ loadName = unoName;
151 int index = unoName->IndexOf('<');
152 if (index != -1)
154 loadName = unoName->Substring(0, index);
155 bIsPolymorphic = true;
157 System::AppDomain^ currentDomain = System::AppDomain::CurrentDomain;
158 cli::array<sr::Assembly^>^ assems = currentDomain->GetAssemblies();
159 for (int i = 0; i < assems->Length; i++)
161 retVal = assems[i]->GetType(loadName, false);
162 if (retVal)
163 break;
166 if (retVal == nullptr)
168 System::String ^ msg = gcnew System::String("A type could not be loaded: ");
169 msg = System::String::Concat(msg, loadName);
170 throw BridgeRuntimeError(mapCliString(msg));
173 if (bIsPolymorphic)
175 retVal = uno::PolymorphicType::GetType(retVal, unoName);
178 catch( System::Exception ^ e)
180 OUString ouMessage(mapCliString(e->Message));
181 throw BridgeRuntimeError(ouMessage);
183 return retVal;
186 System::Type^ mapUnoType(typelib_TypeDescription const * pTD)
188 return mapUnoType(pTD->pWeakRef);
191 System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD)
193 System::Type ^ retVal = nullptr;
194 switch (pTD->eTypeClass)
196 case typelib_TypeClass_VOID:
197 retVal= void::typeid; break;
198 case typelib_TypeClass_CHAR:
199 retVal= System::Char::typeid; break;
200 case typelib_TypeClass_BOOLEAN:
201 retVal= System::Boolean::typeid; break;
202 case typelib_TypeClass_BYTE:
203 retVal= System::Byte::typeid; break;
204 case typelib_TypeClass_SHORT:
205 retVal= System::Int16::typeid; break;
206 case typelib_TypeClass_UNSIGNED_SHORT:
207 retVal= System::UInt16::typeid; break;
208 case typelib_TypeClass_LONG:
209 retVal= System::Int32::typeid; break;
210 case typelib_TypeClass_UNSIGNED_LONG:
211 retVal= System::UInt32::typeid; break;
212 case typelib_TypeClass_HYPER:
213 retVal= System::Int64::typeid; break;
214 case typelib_TypeClass_UNSIGNED_HYPER:
215 retVal= System::UInt64::typeid; break;
216 case typelib_TypeClass_FLOAT:
217 retVal= System::Single::typeid; break;
218 case typelib_TypeClass_DOUBLE:
219 retVal= System::Double::typeid; break;
220 case typelib_TypeClass_STRING:
221 retVal= System::String::typeid; break;
222 case typelib_TypeClass_TYPE:
223 retVal= System::Type::typeid; break;
224 case typelib_TypeClass_ANY:
225 retVal= uno::Any::typeid; break;
226 case typelib_TypeClass_ENUM:
227 case typelib_TypeClass_STRUCT:
228 case typelib_TypeClass_EXCEPTION:
229 retVal= loadCliType(pTD->pTypeName); break;
230 case typelib_TypeClass_INTERFACE:
232 //special handling for XInterface, since it does not exist in cli.
233 OUString usXInterface("com.sun.star.uno.XInterface");
234 if (usXInterface.equals(pTD->pTypeName))
235 retVal= System::Object::typeid;
236 else
237 retVal= loadCliType(pTD->pTypeName);
238 break;
240 case typelib_TypeClass_SEQUENCE:
242 css::uno::TypeDescription seqType(
243 const_cast<typelib_TypeDescriptionReference*>(pTD));
244 typelib_TypeDescriptionReference* pElementTDRef=
245 reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType;
246 switch (pElementTDRef->eTypeClass)
248 case typelib_TypeClass_CHAR:
249 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArChar)); break;
250 case typelib_TypeClass_BOOLEAN:
251 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArBoolean));
252 break;
253 case typelib_TypeClass_BYTE:
254 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArByte));
255 break;
256 case typelib_TypeClass_SHORT:
257 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt16));
258 break;
259 case typelib_TypeClass_UNSIGNED_SHORT:
260 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt16));
261 break;
262 case typelib_TypeClass_LONG:
263 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt32));
264 break;
265 case typelib_TypeClass_UNSIGNED_LONG:
266 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt32));
267 break;
268 case typelib_TypeClass_HYPER:
269 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt64));
270 break;
271 case typelib_TypeClass_UNSIGNED_HYPER:
272 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt64));
273 break;
274 case typelib_TypeClass_FLOAT:
275 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArSingle));
276 break;
277 case typelib_TypeClass_DOUBLE:
278 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArDouble));
279 break;
280 case typelib_TypeClass_STRING:
281 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArString));
282 break;
283 case typelib_TypeClass_TYPE:
284 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArType));
285 break;
286 case typelib_TypeClass_ANY:
287 case typelib_TypeClass_ENUM:
288 case typelib_TypeClass_EXCEPTION:
289 case typelib_TypeClass_STRUCT:
290 case typelib_TypeClass_INTERFACE:
291 case typelib_TypeClass_SEQUENCE:
293 retVal= loadCliType(pTD->pTypeName);
294 break;
296 default:
297 //All cases should be handled by the case statements above
298 OSL_ASSERT(0);
299 break;
301 break;
303 default:
304 OSL_ASSERT(false);
305 break;
307 return retVal;
310 /** Returns an acquired td.
312 typelib_TypeDescriptionReference* mapCliType(System::Type^ cliType)
314 typelib_TypeDescriptionReference* retVal= NULL;
315 if (cliType == nullptr)
317 retVal = * typelib_static_type_getByTypeClass(
318 typelib_TypeClass_VOID );
319 typelib_typedescriptionreference_acquire( retVal );
320 return retVal;
322 //check for Enum first,
323 //because otherwise case System::TypeCode::Int32 applies
324 if (cliType->IsEnum)
326 OUString usTypeName= mapCliTypeName(cliType->FullName);
327 css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
328 retVal= unoType.getTypeLibType();
329 typelib_typedescriptionreference_acquire(retVal);
331 else
333 switch (System::Type::GetTypeCode(cliType))
335 case System::TypeCode::Boolean:
336 retVal = * typelib_static_type_getByTypeClass(
337 typelib_TypeClass_BOOLEAN );
338 typelib_typedescriptionreference_acquire( retVal );
339 break;
340 case System::TypeCode::Char:
341 retVal = * typelib_static_type_getByTypeClass(
342 typelib_TypeClass_CHAR );
343 typelib_typedescriptionreference_acquire( retVal );
344 break;
345 case System::TypeCode::Byte:
346 retVal = * typelib_static_type_getByTypeClass(
347 typelib_TypeClass_BYTE );
348 typelib_typedescriptionreference_acquire( retVal );
349 break;
350 case System::TypeCode::Int16:
351 retVal = * typelib_static_type_getByTypeClass(
352 typelib_TypeClass_SHORT );
353 typelib_typedescriptionreference_acquire( retVal );
354 break;
355 case System::TypeCode::Int32:
356 retVal = * typelib_static_type_getByTypeClass(
357 typelib_TypeClass_LONG );
358 typelib_typedescriptionreference_acquire( retVal );
359 break;
360 case System::TypeCode::Int64:
361 retVal = * typelib_static_type_getByTypeClass(
362 typelib_TypeClass_HYPER );
363 typelib_typedescriptionreference_acquire( retVal );
364 break;
365 case System::TypeCode::UInt16:
366 retVal = * typelib_static_type_getByTypeClass(
367 typelib_TypeClass_UNSIGNED_SHORT );
368 typelib_typedescriptionreference_acquire( retVal );
369 break;
370 case System::TypeCode::UInt32:
371 retVal = * typelib_static_type_getByTypeClass(
372 typelib_TypeClass_UNSIGNED_LONG );
373 typelib_typedescriptionreference_acquire( retVal );
374 break;
375 case System::TypeCode::UInt64:
376 retVal = * typelib_static_type_getByTypeClass(
377 typelib_TypeClass_UNSIGNED_HYPER );
378 typelib_typedescriptionreference_acquire( retVal );
379 break;
380 case System::TypeCode::Single:
381 retVal = * typelib_static_type_getByTypeClass(
382 typelib_TypeClass_FLOAT );
383 typelib_typedescriptionreference_acquire( retVal );
384 break;
385 case System::TypeCode::Double:
386 retVal = * typelib_static_type_getByTypeClass(
387 typelib_TypeClass_DOUBLE );
388 typelib_typedescriptionreference_acquire( retVal );
389 break;
390 case System::TypeCode::String:
391 retVal = * typelib_static_type_getByTypeClass(
392 typelib_TypeClass_STRING );
393 typelib_typedescriptionreference_acquire( retVal );
394 break;
395 default:
396 break;
399 if (retVal == NULL)
401 System::String^ cliTypeName= cliType->FullName;
402 // Void
403 if (const_cast<System::String^>(Constants::sVoid)->Equals(
404 cliTypeName))
406 retVal = * typelib_static_type_getByTypeClass(
407 typelib_TypeClass_VOID );
408 typelib_typedescriptionreference_acquire( retVal );
410 // Type
411 else if (const_cast<System::String^>(Constants::sType)->Equals(
412 cliTypeName))
414 retVal = * typelib_static_type_getByTypeClass(
415 typelib_TypeClass_TYPE );
416 typelib_typedescriptionreference_acquire( retVal );
418 // Any
419 else if (const_cast<System::String^>(Constants::sAny)->Equals(
420 cliTypeName))
422 retVal = * typelib_static_type_getByTypeClass(
423 typelib_TypeClass_ANY );
424 typelib_typedescriptionreference_acquire( retVal );
426 //struct, interfaces, sequences
427 else
429 OUString usTypeName;
430 uno::PolymorphicType ^ poly = dynamic_cast<uno::PolymorphicType^>(cliType);
431 if (poly != nullptr)
432 usTypeName = mapCliTypeName( poly->PolymorphicName);
433 else
434 usTypeName = mapCliTypeName(cliTypeName);
435 typelib_TypeDescription* td = NULL;
436 typelib_typedescription_getByName(&td, usTypeName.pData);
437 if (td)
439 retVal = td->pWeakRef;
440 typelib_typedescriptionreference_acquire(retVal);
441 typelib_typedescription_release(td);
445 if (retVal == NULL)
447 throw BridgeRuntimeError("[cli_uno bridge] mapCliType():could not map type: " + mapCliString(cliType->FullName));
449 return retVal;
453 Otherwise a leading "unoidl." is removed.
455 System::String^ mapUnoTypeName(rtl_uString const * typeName)
457 OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
458 st::StringBuilder^ buf= gcnew st::StringBuilder();
459 //determine if the type is a sequence and its dimensions
460 int dims= 0;
461 if (usUnoName[0] == '[')
463 sal_Int32 index= 1;
464 while (true)
466 if (usUnoName[index++] == ']')
467 dims++;
468 if (usUnoName[index++] != '[')
469 break;
471 usUnoName = usUnoName.copy(index - 1);
473 System::String ^ sUnoName = mapUnoString(usUnoName.pData);
474 if (sUnoName->Equals(const_cast<System::String^>(Constants::usBool)))
475 buf->Append(const_cast<System::String^>(Constants::sBoolean));
476 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usChar)))
477 buf->Append(const_cast<System::String^>(Constants::sChar));
478 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usByte)))
479 buf->Append(const_cast<System::String^>(Constants::sByte));
480 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usShort)))
481 buf->Append(const_cast<System::String^>(Constants::sInt16));
482 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUShort)))
483 buf->Append(const_cast<System::String^>(Constants::sUInt16));
484 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usLong)))
485 buf->Append(const_cast<System::String^>(Constants::sInt32));
486 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usULong)))
487 buf->Append(const_cast<System::String^>(Constants::sUInt32));
488 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usHyper)))
489 buf->Append(const_cast<System::String^>(Constants::sInt64));
490 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUHyper)))
491 buf->Append(const_cast<System::String^>(Constants::sUInt64));
492 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usFloat)))
493 buf->Append(const_cast<System::String^>(Constants::sSingle));
494 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usDouble)))
495 buf->Append(const_cast<System::String^>(Constants::sDouble));
496 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usString)))
497 buf->Append(const_cast<System::String^>(Constants::sString));
498 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usVoid)))
499 buf->Append(const_cast<System::String^>(Constants::sVoid));
500 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usType)))
501 buf->Append(const_cast<System::String^>(Constants::sType));
502 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usXInterface)))
503 buf->Append(const_cast<System::String^>(Constants::sObject));
504 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usAny)))
506 buf->Append(const_cast<System::String^>(Constants::sAny));
508 else
510 //put "unoidl." at the beginning
511 buf->Append(const_cast<System::String^>(Constants::sUnoidl));
512 //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
513 System::String ^ sName = mapUnoPolymorphicName(sUnoName);
514 buf->Append(sName);
516 // append []
517 for (;dims--;)
518 buf->Append(const_cast<System::String^>(Constants::sBrackets));
520 return buf->ToString();
523 /** For example, there is a uno type
524 com.sun.star.Foo<char, long>.
525 The values in the type list
526 are uno types and are replaced by cli types, such as System.Char,
527 System.Int32, etc.
528 The prefix unoidl is not added.
530 inline System::String^ mapUnoPolymorphicName(System::String^ unoName)
532 return mapPolymorphicName(unoName, false);
535 /** For example, there is a type name such as
536 com.sun.star.Foo<System.Char, System.Int32>.
537 The values in the type list
538 are CLI types and are replaced by uno types, such as char,
539 long, etc.
540 The prefix unoidl remains.
542 inline System::String^ mapCliPolymorphicName(System::String^ unoName)
544 return mapPolymorphicName(unoName, true);
547 System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno)
549 int index = unoName->IndexOf('<');
550 if (index == -1)
551 return unoName;
553 System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256);
554 builder->Append(unoName->Substring(0, index +1 ));
556 //Find the first occurrence of ','
557 //If the parameter is a polymorphic struct then we need to ignore everything
558 //between the brackets because it can also contain commas
559 //get the type list within < and >
560 int endIndex = unoName->Length - 1;
561 index++;
562 int cur = index;
563 int countParams = 0;
564 while (cur <= endIndex)
566 System::Char c = unoName[cur];
567 if (c == ',' || c == '>')
569 //insert a comma if needed
570 if (countParams != 0)
571 builder->Append(",");
572 countParams++;
573 System::String ^ sParam = unoName->Substring(index, cur - index);
574 //skip the comma
575 cur++;
576 //the index to the beginning of the next param
577 index = cur;
578 if (bCliToUno)
580 builder->Append(mapCliTypeName(sParam).getStr());
582 else
584 OUString s = mapCliString(sParam);
585 builder->Append(mapUnoTypeName(s.pData));
588 else if (c == '<')
590 cur++;
591 //continue until the matching '>'
592 int numNested = 0;
593 for (;;cur++)
595 System::Char curChar = unoName[cur];
596 if (curChar == '<')
598 numNested ++;
600 else if (curChar == '>')
602 if (numNested > 0)
603 numNested--;
604 else
605 break;
609 cur++;
612 builder->Append((System::Char) '>');
613 return builder->ToString();
616 OUString mapCliTypeName(System::String^ typeName)
618 int dims= 0;
619 // Array? determine the "rank" (number of "[]")
620 // move from the rightmost end to the left, for example
621 // unoidl.PolymorphicStruct<System.Char[]>[]
622 // has only a "dimension" of 1
623 int cur = typeName->Length - 1;
624 bool bRightBracket = false;
625 while (cur >= 0)
627 System::Char c = typeName[cur];
628 if (c == ']')
630 bRightBracket = true;
632 else if (c == '[')
634 if (!bRightBracket)
635 throw BridgeRuntimeError(
636 "Typename is wrong. No matching brackets for sequence. Name is: " +
637 mapCliString(typeName));
638 bRightBracket = false;
639 dims ++;
641 else
643 if (bRightBracket)
644 throw BridgeRuntimeError(
645 "Typename is wrong. No matching brackets for sequence. Name is: " +
646 mapCliString(typeName));
647 break;
649 cur--;
652 if (bRightBracket || cur < 0)
653 throw BridgeRuntimeError(
654 "Typename is wrong. " +
655 mapCliString(typeName));
657 typeName = typeName->Substring(0, cur + 1);
659 System::Text::StringBuilder ^ buf = gcnew System::Text::StringBuilder(512);
661 //Put the "[]" at the beginning of the uno type name
662 for (;dims--;)
663 buf->Append(const_cast<System::String^>(Constants::usBrackets));
665 if (typeName->Equals(const_cast<System::String^>(Constants::sBoolean)))
666 buf->Append(const_cast<System::String^>(Constants::usBool));
667 else if (typeName->Equals(const_cast<System::String^>(Constants::sChar)))
668 buf->Append(const_cast<System::String^>(Constants::usChar));
669 else if (typeName->Equals(const_cast<System::String^>(Constants::sByte)))
670 buf->Append(const_cast<System::String^>(Constants::usByte));
671 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt16)))
672 buf->Append(const_cast<System::String^>(Constants::usShort));
673 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt16)))
674 buf->Append(const_cast<System::String^>(Constants::usUShort));
675 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt32)))
676 buf->Append(const_cast<System::String^>(Constants::usLong));
677 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt32)))
678 buf->Append(const_cast<System::String^>(Constants::usULong));
679 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt64)))
680 buf->Append(const_cast<System::String^>(Constants::usHyper));
681 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt64)))
682 buf->Append(const_cast<System::String^>(Constants::usUHyper));
683 else if (typeName->Equals(const_cast<System::String^>(Constants::sSingle)))
684 buf->Append(const_cast<System::String^>(Constants::usFloat));
685 else if (typeName->Equals(const_cast<System::String^>(Constants::sDouble)))
686 buf->Append(const_cast<System::String^>(Constants::usDouble));
687 else if (typeName->Equals(const_cast<System::String^>(Constants::sString)))
688 buf->Append(const_cast<System::String^>(Constants::usString));
689 else if (typeName->Equals(const_cast<System::String^>(Constants::sVoid)))
690 buf->Append(const_cast<System::String^>(Constants::usVoid));
691 else if (typeName->Equals(const_cast<System::String^>(Constants::sType)))
692 buf->Append(const_cast<System::String^>(Constants::usType));
693 else if (typeName->Equals(const_cast<System::String^>(Constants::sObject)))
694 buf->Append(const_cast<System::String^>(Constants::usXInterface));
695 else if (typeName->Equals(const_cast<System::String^>(Constants::sAny)))
696 buf->Append(const_cast<System::String^>(Constants::usAny));
697 else
699 System::String ^ sName = mapCliPolymorphicName(typeName);
700 int i= sName->IndexOf(L'.');
701 buf->Append(sName->Substring(i + 1));
703 return mapCliString(buf->ToString());
706 /** Maps uno types to dot net types.
707 * If uno_data is null then the type description is converted to System::Type
709 inline System::String^ mapUnoString( rtl_uString const * data)
711 OSL_ASSERT(data);
712 return gcnew System::String((__wchar_t*) data->buffer, 0, data->length);
715 OUString mapCliString(System::String ^ data)
718 if (data != nullptr)
720 static_assert(sizeof(wchar_t) == sizeof(sal_Unicode), "char mismatch");
721 pin_ptr<wchar_t const> pdata= PtrToStringChars(data);
722 return OUString(
723 reinterpret_cast<sal_Unicode const *>(pdata),
724 const_cast<System::String^>(data)->Length);
726 else
728 return OUString();
732 // ToDo convert cli types to expected types, e.g a long to a short where the uno type
733 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used
734 // @param assign the uno_data has to be destructed (in/out args)
735 void Bridge::map_to_uno(void * uno_data, System::Object^ cli_data,
736 typelib_TypeDescriptionReference * type,
737 bool assign) const
739 try{
740 switch (type->eTypeClass)
742 case typelib_TypeClass_VOID:
743 break;
744 case typelib_TypeClass_CHAR:
746 System::Char aChar= *safe_cast<System::Char^>(cli_data);
747 *(sal_Unicode*) uno_data= aChar;
748 break;
750 case typelib_TypeClass_BOOLEAN:
752 System::Boolean aBool= *safe_cast<System::Boolean^>(cli_data);
753 *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
754 break;
756 case typelib_TypeClass_BYTE:
758 System::Byte aByte= *safe_cast<System::Byte^>(cli_data);
759 *(sal_Int8*) uno_data= aByte;
760 break;
762 case typelib_TypeClass_SHORT:
764 System::Int16 aShort= *safe_cast<System::Int16^>(cli_data);
765 *(sal_Int16*) uno_data= aShort;
766 break;
768 case typelib_TypeClass_UNSIGNED_SHORT:
770 System::UInt16 aUShort= *safe_cast<System::UInt16^>(cli_data);
771 *(sal_uInt16*) uno_data= aUShort;
772 break;
774 case typelib_TypeClass_LONG:
776 System::Int32 aLong= *safe_cast<System::Int32^>(cli_data);
777 *(sal_Int32*) uno_data= aLong;
778 break;
780 case typelib_TypeClass_UNSIGNED_LONG:
782 System::UInt32 aULong= *safe_cast<System::UInt32^>(cli_data);
783 *(sal_uInt32*) uno_data= aULong;
784 break;
786 case typelib_TypeClass_HYPER:
788 System::Int64 aHyper= *safe_cast<System::Int64^>(cli_data);
789 *(sal_Int64*) uno_data= aHyper;
790 break;
792 case typelib_TypeClass_UNSIGNED_HYPER:
794 System::UInt64 aLong= *safe_cast<System::UInt64^>(cli_data);
795 *(sal_uInt64*) uno_data= aLong;
796 break;
798 case typelib_TypeClass_FLOAT:
800 System::Single aFloat= *safe_cast<System::Single^>(cli_data);
801 *(float*) uno_data= aFloat;
802 break;
804 case typelib_TypeClass_DOUBLE:
806 System::Double aDouble= *safe_cast<System::Double^>(cli_data);
807 *(double*) uno_data= aDouble;
808 break;
810 case typelib_TypeClass_STRING:
812 if (assign && *(rtl_uString**) uno_data)
813 rtl_uString_release(*(rtl_uString**) uno_data);
815 *(rtl_uString **)uno_data = 0;
816 if (cli_data == nullptr)
818 rtl_uString_new((rtl_uString**) uno_data);
820 else
822 System::String ^s= safe_cast<System::String^>(cli_data);
823 pin_ptr<const wchar_t> pdata= PtrToStringChars(s);
824 rtl_uString_newFromStr_WithLength(
825 reinterpret_cast<rtl_uString **>(uno_data),
826 reinterpret_cast<sal_Unicode const *>(pdata), s->Length);
828 break;
830 case typelib_TypeClass_TYPE:
832 typelib_TypeDescriptionReference* td= mapCliType(safe_cast<System::Type^>(
833 cli_data));
834 if (assign)
836 typelib_typedescriptionreference_release(
837 *(typelib_TypeDescriptionReference **)uno_data );
839 *(typelib_TypeDescriptionReference **)uno_data = td;
840 break;
842 case typelib_TypeClass_ANY:
844 uno_Any * pAny = (uno_Any *)uno_data;
845 if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any
847 if (assign)
848 uno_any_destruct( pAny, 0 );
849 uno_any_construct( pAny, 0, 0, 0 );
850 break;
852 uno::Any aAny= *safe_cast<uno::Any^>(cli_data);
853 css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
855 if (assign)
856 uno_any_destruct( pAny, 0 );
860 switch (value_td.getTypeClass())
862 case css::uno::TypeClass_VOID:
863 pAny->pData = &pAny->pReserved;
864 break;
865 case css::uno::TypeClass_CHAR:
866 pAny->pData = &pAny->pReserved;
867 *(sal_Unicode*) &pAny->pReserved = *safe_cast<System::Char^>(aAny.Value);
868 break;
869 case css::uno::TypeClass_BOOLEAN:
870 pAny->pData = &pAny->pReserved;
871 *(sal_Bool *) &pAny->pReserved = *safe_cast<System::Boolean^>(aAny.Value);
872 break;
873 case css::uno::TypeClass_BYTE:
874 pAny->pData = &pAny->pReserved;
875 *(sal_Int8*) &pAny->pReserved = *safe_cast<System::Byte^>(aAny.Value);
876 break;
877 case css::uno::TypeClass_SHORT:
878 pAny->pData = &pAny->pReserved;
879 *(sal_Int16*) &pAny->pReserved = *safe_cast<System::Int16^>(aAny.Value);
880 break;
881 case css::uno::TypeClass_UNSIGNED_SHORT:
882 pAny->pData = &pAny->pReserved;
883 *(sal_uInt16*) &pAny->pReserved = *safe_cast<System::UInt16^>(aAny.Value);
884 break;
885 case css::uno::TypeClass_LONG:
886 pAny->pData = &pAny->pReserved;
887 *(sal_Int32*) &pAny->pReserved = *safe_cast<System::Int32^>(aAny.Value);
888 break;
889 case css::uno::TypeClass_UNSIGNED_LONG:
890 pAny->pData = &pAny->pReserved;
891 *(sal_uInt32*) &pAny->pReserved = *safe_cast<System::UInt32^>(aAny.Value);
892 break;
893 case css::uno::TypeClass_HYPER:
894 if (sizeof (sal_Int64) <= sizeof (void *))
896 pAny->pData = &pAny->pReserved;
897 *(sal_Int64*) &pAny->pReserved = *safe_cast<System::Int64^>(aAny.Value);
899 else
901 std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
902 *(sal_Int64 *) mem.get()= *safe_cast<System::Int64^>(aAny.Value);
903 pAny->pData = mem.release();
905 break;
906 case css::uno::TypeClass_UNSIGNED_HYPER:
907 if (sizeof (sal_uInt64) <= sizeof (void *))
909 pAny->pData = &pAny->pReserved;
910 *(sal_uInt64*) &pAny->pReserved = *safe_cast<System::UInt64^>(aAny.Value);
912 else
914 std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
915 *(sal_uInt64 *) mem.get()= *safe_cast<System::UInt64^>(aAny.Value);
916 pAny->pData = mem.release();
918 break;
919 case css::uno::TypeClass_FLOAT:
920 if (sizeof (float) <= sizeof (void *))
922 pAny->pData = &pAny->pReserved;
923 *(float*) &pAny->pReserved = *safe_cast<System::Single^>(aAny.Value);
925 else
927 std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
928 *(float*) mem.get() = *safe_cast<System::Single^>(aAny.Value);
929 pAny->pData = mem.release();
931 break;
932 case css::uno::TypeClass_DOUBLE:
933 if (sizeof (double) <= sizeof (void *))
935 pAny->pData = &pAny->pReserved;
936 *(double*) &pAny->pReserved= *safe_cast<System::Double^>(aAny.Value);
938 else
940 std::unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
941 *(double*) mem.get()= *safe_cast<System::Double^>(aAny.Value);
942 pAny->pData= mem.release();
944 break;
945 case css::uno::TypeClass_STRING: // anies often contain strings; copy string directly
947 pAny->pData= &pAny->pReserved;
948 OUString _s = mapCliString(static_cast<System::String^>(aAny.Value));
949 pAny->pReserved= _s.pData;
950 rtl_uString_acquire(_s.pData);
951 break;
953 case css::uno::TypeClass_TYPE:
954 case css::uno::TypeClass_ENUM: //ToDo copy enum direct
955 case css::uno::TypeClass_SEQUENCE:
956 case css::uno::TypeClass_INTERFACE:
957 pAny->pData = &pAny->pReserved;
958 pAny->pReserved = 0;
959 map_to_uno(
960 &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
961 false /* no assign */);
962 break;
963 case css::uno::TypeClass_STRUCT:
964 case css::uno::TypeClass_EXCEPTION:
966 css::uno::Type anyType(value_td);
967 typelib_TypeDescription* td= NULL;
968 anyType.getDescription(&td);
969 std::unique_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
970 typelib_typedescription_release(td);
971 map_to_uno(
972 mem.get(), aAny.Value, value_td.getTypeLibType(),
973 false /* no assign */);
974 pAny->pData = mem.release();
975 break;
977 default:
979 throw BridgeRuntimeError("[map_to_uno():" + value_td.getTypeName() + "] unsupported value type of any!");
983 catch(System::InvalidCastException^ )
985 // ToDo check this
986 if (assign)
987 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
988 OUString str = "[map_to_uno():Any" + value_td.getTypeName() + "]The Any type " + value_td.getTypeName() + " does not correspond to its value type: ";
989 if(aAny.Value != nullptr)
991 css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
992 str += td.getTypeName();
994 if (assign)
995 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
996 throw BridgeRuntimeError(str);
998 catch (BridgeRuntimeError& )
1000 if (assign)
1001 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1002 throw;
1004 catch (...)
1006 if (assign)
1007 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1008 throw;
1011 pAny->pType = value_td.getTypeLibType();
1012 typelib_typedescriptionreference_acquire(pAny->pType);
1013 break;
1015 case typelib_TypeClass_ENUM:
1017 // InvalidCastException is caught at the end of this method
1018 System::Int32 aEnum= System::Convert::ToInt32((cli_data));
1019 *(sal_Int32*) uno_data = aEnum;
1020 break;
1022 case typelib_TypeClass_STRUCT:
1023 case typelib_TypeClass_EXCEPTION:
1025 css::uno::TypeDescription td(type);
1026 typelib_CompoundTypeDescription * comp_td =
1027 (typelib_CompoundTypeDescription*) td.get();
1029 typelib_StructTypeDescription * struct_td = NULL;
1030 if (type->eTypeClass == typelib_TypeClass_STRUCT)
1031 struct_td = (typelib_StructTypeDescription*) td.get();
1033 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1034 ::typelib_typedescription_complete(
1035 (typelib_TypeDescription**) & comp_td );
1037 sal_Int32 nMembers = comp_td->nMembers;
1038 boolean bException= false;
1039 System::Type^ cliType = nullptr;
1040 if (cli_data)
1041 cliType = cli_data->GetType();
1043 if (0 != comp_td->pBaseTypeDescription)
1045 map_to_uno(
1046 uno_data, cli_data,
1047 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
1048 assign);
1050 sal_Int32 nPos = 0;
1053 OUString usUnoException("com.sun.star.uno.Exception");
1054 for (; nPos < nMembers; ++nPos)
1056 typelib_TypeDescriptionReference * member_type= comp_td->ppTypeRefs[nPos];
1057 System::Object^ val= nullptr;
1058 if (cli_data != nullptr)
1060 sr::FieldInfo^ aField= cliType->GetField(
1061 mapUnoString(comp_td->ppMemberNames[nPos]));
1062 // special case for Exception.Message property
1063 // The com.sun.star.uno.Exception.Message field is mapped to the
1064 // System.Exception property. Type.GetField("Message") returns null
1065 if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1066 {// get Exception.Message property
1067 OUString usMessageMember("Message");
1068 if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
1070 sr::PropertyInfo^ pi= cliType->GetProperty(
1071 mapUnoString(comp_td->ppMemberNames[nPos]));
1072 val= pi->GetValue(cli_data, nullptr);
1074 else
1076 throw BridgeRuntimeError("[map_to_uno(): Member: " + OUString::unacquired(&comp_td->ppMemberNames[nPos]));
1079 else
1081 val= aField->GetValue(cli_data);
1084 void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
1085 //When using polymorphic structs then the parameterized members can be null.
1086 //Then we set a default value.
1087 bool bDefault = (struct_td != NULL
1088 && struct_td->pParameterizedTypes != NULL
1089 && struct_td->pParameterizedTypes[nPos] == sal_True
1090 && val == nullptr)
1091 || cli_data == nullptr;
1092 switch (member_type->eTypeClass)
1094 case typelib_TypeClass_CHAR:
1095 if (bDefault)
1096 *(sal_Unicode*) p = 0;
1097 else
1098 *(sal_Unicode*) p = *safe_cast<System::Char^>(val);
1099 break;
1100 case typelib_TypeClass_BOOLEAN:
1101 if (bDefault)
1102 *(sal_Bool*) p = sal_False;
1103 else
1104 *(sal_Bool*) p = *safe_cast<System::Boolean^>(val);
1105 break;
1106 case typelib_TypeClass_BYTE:
1107 if (bDefault)
1108 *(sal_Int8*) p = 0;
1109 else
1110 *(sal_Int8*) p = *safe_cast<System::Byte^>(val);
1111 break;
1112 case typelib_TypeClass_SHORT:
1113 if (bDefault)
1114 *(sal_Int16*) p = 0;
1115 else
1116 *(sal_Int16*) p = *safe_cast<System::Int16^>(val);
1117 break;
1118 case typelib_TypeClass_UNSIGNED_SHORT:
1119 if (bDefault)
1120 *(sal_uInt16*) p = 0;
1121 else
1122 *(sal_uInt16*) p = *safe_cast<System::UInt16^>(val);
1123 break;
1124 case typelib_TypeClass_LONG:
1125 if (bDefault)
1126 *(sal_Int32*) p = 0;
1127 else
1128 *(sal_Int32*) p = *safe_cast<System::Int32^>(val);
1129 break;
1130 case typelib_TypeClass_UNSIGNED_LONG:
1131 if (bDefault)
1132 *(sal_uInt32*) p = 0;
1133 else
1134 *(sal_uInt32*) p = *safe_cast<System::UInt32^>(val);
1135 break;
1136 case typelib_TypeClass_HYPER:
1137 if (bDefault)
1138 *(sal_Int64*) p = 0;
1139 else
1140 *(sal_Int64*) p = *safe_cast<System::Int64^>(val);
1141 break;
1142 case typelib_TypeClass_UNSIGNED_HYPER:
1143 if (bDefault)
1144 *(sal_uInt64*) p = 0;
1145 else
1146 *(sal_uInt64*) p= *safe_cast<System::UInt64^>(val);
1147 break;
1148 case typelib_TypeClass_FLOAT:
1149 if (bDefault)
1150 *(float*) p = 0.;
1151 else
1152 *(float*) p = *safe_cast<System::Single^>(val);
1153 break;
1154 case typelib_TypeClass_DOUBLE:
1155 if (bDefault)
1156 *(double*) p = 0.;
1157 else
1158 *(double*) p = *safe_cast<System::Double^>(val);
1159 break;
1160 default:
1161 { // ToDo enum, should be converted here
1162 map_to_uno(p, val, member_type, assign);
1163 break;
1168 catch (BridgeRuntimeError& e)
1170 bException= true;
1171 OUString str = "[map_to_uno():";
1172 if (cliType)
1174 str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]) + " ";
1176 str += e.m_message;
1177 throw BridgeRuntimeError(str);
1179 catch (System::InvalidCastException^ )
1181 bException= true;
1182 OUString str = "[map_to_uno():";
1183 if (cliType)
1185 str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]);
1187 str += "] Value has not the required type.";
1188 throw BridgeRuntimeError(str);
1190 catch (...)
1192 OSL_ASSERT(0);
1193 bException= true;
1194 throw;
1196 __finally
1198 if (bException && !assign) // if assign then caller cleans up
1200 // cleanup the members which we have converted so far
1201 for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
1203 uno_type_destructData(
1204 uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
1206 if (0 != comp_td->pBaseTypeDescription)
1208 uno_destructData(
1209 uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
1213 break;
1215 case typelib_TypeClass_SEQUENCE:
1217 TypeDescr td( type );
1218 typelib_TypeDescriptionReference * element_type =
1219 ((typelib_IndirectTypeDescription *)td.get())->pType;
1221 std::unique_ptr< rtl_mem > seq;
1223 System::Array^ ar = nullptr;
1224 if (cli_data != nullptr)
1226 ar = safe_cast<System::Array^>(cli_data);
1227 sal_Int32 nElements = ar->GetLength(0);
1231 switch (element_type->eTypeClass)
1233 case typelib_TypeClass_CHAR:
1234 seq = seq_allocate(nElements, sizeof (sal_Unicode));
1235 sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
1236 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1237 break;
1238 case typelib_TypeClass_BOOLEAN:
1239 seq = seq_allocate(nElements, sizeof (sal_Bool));
1240 sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
1241 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1242 break;
1243 case typelib_TypeClass_BYTE:
1244 seq = seq_allocate( nElements, sizeof (sal_Int8) );
1245 sri::Marshal::Copy(safe_cast<cli::array<System::Byte>^>(cli_data), 0,
1246 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1247 break;
1248 case typelib_TypeClass_SHORT:
1249 seq = seq_allocate(nElements, sizeof (sal_Int16));
1250 sri::Marshal::Copy(safe_cast<cli::array<System::Int16>^>(cli_data), 0,
1251 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1252 break;
1253 case typelib_TypeClass_UNSIGNED_SHORT:
1254 seq = seq_allocate( nElements, sizeof (sal_uInt16) );
1255 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int16>^>(
1256 safe_cast<cli::array<System::UInt16>^>(cli_data)), 0,
1257 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1258 break;
1259 case typelib_TypeClass_LONG:
1260 seq = seq_allocate(nElements, sizeof (sal_Int32));
1261 sri::Marshal::Copy(safe_cast<cli::array<System::Int32>^>(cli_data), 0,
1262 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1263 break;
1264 case typelib_TypeClass_UNSIGNED_LONG:
1265 seq = seq_allocate( nElements, sizeof (sal_uInt32) );
1266 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int32>^>(
1267 safe_cast<cli::array<System::UInt32>^>(cli_data)), 0,
1268 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1269 break;
1270 case typelib_TypeClass_HYPER:
1271 seq = seq_allocate(nElements, sizeof (sal_Int64));
1272 sri::Marshal::Copy(safe_cast<cli::array<System::Int64>^>(cli_data), 0,
1273 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1274 break;
1275 case typelib_TypeClass_UNSIGNED_HYPER:
1276 seq = seq_allocate(nElements, sizeof (sal_uInt64));
1277 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int64>^>(
1278 safe_cast<cli::array<System::UInt64>^>(cli_data)), 0,
1279 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1280 break;
1281 case typelib_TypeClass_FLOAT:
1282 seq = seq_allocate(nElements, sizeof (float));
1283 sri::Marshal::Copy(safe_cast<cli::array<System::Single>^>(cli_data), 0,
1284 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1285 break;
1286 case typelib_TypeClass_DOUBLE:
1287 seq = seq_allocate(nElements, sizeof (double));
1288 sri::Marshal::Copy(safe_cast<cli::array<System::Double>^>(cli_data), 0,
1289 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1290 break;
1291 case typelib_TypeClass_STRING:
1293 seq = seq_allocate(nElements, sizeof (rtl_uString*));
1294 cli::array<System::String^>^ arStr= safe_cast<cli::array<System::String^>^>(cli_data);
1295 for (int i= 0; i < nElements; i++)
1297 pin_ptr<const wchar_t> pdata= PtrToStringChars(arStr[i]);
1298 rtl_uString** pStr= & ((rtl_uString**) &
1299 ((uno_Sequence*) seq.get())->elements)[i];
1300 *pStr= NULL;
1301 rtl_uString_newFromStr_WithLength(
1302 pStr,
1303 reinterpret_cast<sal_Unicode const *>(pdata),
1304 arStr[i]->Length);
1306 break;
1308 case typelib_TypeClass_ENUM:
1309 seq = seq_allocate(nElements, sizeof (sal_Int32));
1310 for (int i= 0; i < nElements; i++)
1312 ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
1313 System::Convert::ToInt32(ar->GetValue(i));
1315 break;
1316 case typelib_TypeClass_TYPE:
1317 case typelib_TypeClass_ANY:
1318 case typelib_TypeClass_STRUCT:
1319 case typelib_TypeClass_EXCEPTION:
1320 case typelib_TypeClass_SEQUENCE:
1321 case typelib_TypeClass_INTERFACE:
1323 TypeDescr element_td( element_type );
1324 seq = seq_allocate( nElements, element_td.get()->nSize );
1326 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
1330 void * p= ((uno_Sequence *) seq.get())->elements +
1331 (nPos * element_td.get()->nSize);
1332 System::Object^ elemData= safe_cast<System::Array^>(cli_data)->GetValue(System::Int32(nPos));
1333 map_to_uno(
1334 p, elemData, element_td.get()->pWeakRef,
1335 false /* no assign */);
1337 catch (...)
1339 // cleanup
1340 for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
1342 void * p =
1343 ((uno_Sequence *)seq.get())->elements +
1344 (nCleanPos * element_td.get()->nSize);
1345 uno_destructData( p, element_td.get(), 0 );
1347 throw;
1350 break;
1352 default:
1354 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) +
1355 "] unsupported sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
1359 catch (BridgeRuntimeError& e)
1361 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] conversion failed\n " + e.m_message);
1363 catch (System::InvalidCastException^ )
1365 // Ok, checked
1366 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName) +
1367 "] could not convert sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
1369 catch (...)
1371 OSL_ASSERT(0);
1372 throw;
1374 __finally
1376 if (assign)
1377 uno_destructData( uno_data, td.get(), 0 );
1380 else
1382 seq = seq_allocate(0, sizeof (sal_Int32));
1384 *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
1385 break;
1387 case typelib_TypeClass_INTERFACE:
1389 if (assign)
1391 uno_Interface * p = *(uno_Interface **)uno_data;
1392 if (0 != p)
1393 (*p->release)( p );
1395 if (nullptr == cli_data) // null-ref
1397 *(uno_Interface **)uno_data = 0;
1399 else
1401 TypeDescr td( type );
1402 uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
1403 *(uno_Interface **)uno_data = pUnoI;
1405 break;
1407 default:
1409 //ToDo check
1410 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
1414 // BridgeRuntimeError are allowed to be thrown
1415 catch (System::InvalidCastException^ )
1417 //ToDo check
1418 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] could not convert type!");
1420 catch (System::NullReferenceException ^ e)
1422 throw BridgeRuntimeError("[map_to_uno()] Illegal null reference passed!\n" + mapCliString(e->StackTrace));
1424 catch (BridgeRuntimeError& )
1426 throw;
1428 catch (...)
1430 OSL_ASSERT(0);
1431 throw;
1436 @param info
1437 The expected target type. Currently info is provided when this method is called
1438 to convert the in/out and out parameters of a call from cli to uno. Then info
1439 is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
1440 @param bDontCreateObj
1441 false - a new object is created which holds the mapped uno value and is assigned to
1442 cli_data.
1443 true - cli_data already contains the newly constructed object. This is the case if
1444 a struct is converted then on the first call to map_to_cli the new object is created.
1445 If the struct inherits another struct then this function is called recursively while the
1446 newly created object is passed in cli_data.
1448 void Bridge::map_to_cli(
1449 System::Object^ *cli_data, void const * uno_data,
1450 typelib_TypeDescriptionReference * type, System::Type^ info,
1451 bool bDontCreateObj) const
1453 switch (type->eTypeClass)
1455 case typelib_TypeClass_CHAR:
1456 *cli_data= *(__wchar_t const*)uno_data;
1457 break;
1458 case typelib_TypeClass_BOOLEAN:
1459 *cli_data = (*(bool const*)uno_data) == sal_True;
1460 break;
1461 case typelib_TypeClass_BYTE:
1462 *cli_data = *(unsigned char const*) uno_data;
1463 break;
1464 case typelib_TypeClass_SHORT:
1465 *cli_data= *(short const*) uno_data;
1466 break;
1467 case typelib_TypeClass_UNSIGNED_SHORT:
1468 *cli_data= *(unsigned short const*) uno_data;
1469 break;
1470 case typelib_TypeClass_LONG:
1471 *cli_data= *(int const*) uno_data;
1472 break;
1473 case typelib_TypeClass_UNSIGNED_LONG:
1474 *cli_data= *(unsigned int const*) uno_data;
1475 break;
1476 case typelib_TypeClass_HYPER:
1477 *cli_data= *(__int64 const*) uno_data;
1478 break;
1479 case typelib_TypeClass_UNSIGNED_HYPER:
1480 *cli_data= *(unsigned __int64 const*) uno_data;
1481 break;
1482 case typelib_TypeClass_FLOAT:
1483 *cli_data= *(float const*) uno_data;
1484 break;
1485 case typelib_TypeClass_DOUBLE:
1486 *cli_data= *(double const*) uno_data;
1487 break;
1488 case typelib_TypeClass_STRING:
1490 rtl_uString const* sVal= NULL;
1491 sVal= *(rtl_uString* const*) uno_data;
1492 *cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length);
1493 break;
1495 case typelib_TypeClass_TYPE:
1497 *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
1498 break;
1500 case typelib_TypeClass_ANY:
1502 uno_Any const * pAny = (uno_Any const *)uno_data;
1503 if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
1505 System::Object^ objCli= nullptr;
1506 map_to_cli(
1507 &objCli, pAny->pData, pAny->pType, nullptr,
1508 false);
1510 uno::Any anyVal(mapUnoType(pAny->pType), objCli);
1511 *cli_data= anyVal;
1513 else
1514 { // void any
1515 *cli_data= uno::Any::VOID;
1517 break;
1519 case typelib_TypeClass_ENUM:
1521 if (info != nullptr)
1523 OSL_ASSERT(info->IsByRef);
1524 info= info->GetElementType();
1525 *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
1527 else
1528 *cli_data= System::Enum::ToObject(
1529 mapUnoType(type), *(System::Int32*) uno_data);
1530 break;
1532 case typelib_TypeClass_STRUCT:
1533 case typelib_TypeClass_EXCEPTION:
1535 TypeDescr td( type );
1536 typelib_CompoundTypeDescription * comp_td =
1537 (typelib_CompoundTypeDescription *) td.get();
1538 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1539 ::typelib_typedescription_complete(
1540 (typelib_TypeDescription**) & comp_td );
1543 //create the type
1544 System::Type^ cliType= loadCliType(td.get()->pTypeName);
1545 //detect if we recursively convert inherited structures
1546 //If this point is reached because of a recursive call during covering a
1547 //struct then we must not create a new object rather we use the one in
1548 // cli_data argument.
1549 System::Object^ cliObj;
1550 if (bDontCreateObj)
1551 cliObj = *cli_data; // recursive call
1552 else
1554 //Special handling for Exception conversion. We must call constructor System::Exception
1555 //to pass the message string
1556 if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType))
1558 //We need to get the Message field. Therefore we must obtain the offset from
1559 //the typedescription. The base interface of all exceptions is
1560 //com::sun::star::uno::Exception which contains the message
1561 typelib_CompoundTypeDescription* pCTD = comp_td;
1562 while (pCTD->pBaseTypeDescription)
1563 pCTD = pCTD->pBaseTypeDescription;
1564 int nPos = -1;
1566 OUString usMessageMember("Message");
1567 for (int i = 0; i < pCTD->nMembers; i ++)
1569 if (usMessageMember.equals(pCTD->ppMemberNames[i]))
1571 nPos = i;
1572 break;
1575 OSL_ASSERT (nPos != -1);
1576 int offset = pCTD->pMemberOffsets[nPos];
1577 //With the offset within the exception we can get the message string
1578 System::String^ sMessage = mapUnoString(*(rtl_uString**)
1579 ((char*) uno_data + offset));
1580 //We need to find a constructor for the exception that takes the message string
1581 //We assume that the first argument is the message string
1582 cli::array<sr::ConstructorInfo^>^ arCtorInfo = cliType->GetConstructors();
1583 sr::ConstructorInfo^ ctorInfo = nullptr;
1584 int numCtors = arCtorInfo->Length;
1585 //Constructor must at least have 2 params for the base
1586 //unoidl.com.sun.star.uno.Exception (String, Object);
1587 cli::array<sr::ParameterInfo^>^ arParamInfo;
1588 for (int i = 0; i < numCtors; i++)
1590 arParamInfo = arCtorInfo[i]->GetParameters();
1591 if (arParamInfo->Length < 2)
1592 continue;
1593 ctorInfo = arCtorInfo[i];
1594 break;
1596 OSL_ASSERT(arParamInfo[0]->ParameterType->Equals(System::String::typeid)
1597 && arParamInfo[1]->ParameterType->Equals(System::Object::typeid)
1598 && arParamInfo[0]->Position == 0
1599 && arParamInfo[1]->Position == 1);
1600 //Prepare parameters for constructor
1601 int numArgs = arParamInfo->Length;
1602 cli::array<System::Object^>^ args = gcnew cli::array<System::Object^>(numArgs);
1603 //only initialize the first argument with the message
1604 args[0] = sMessage;
1605 cliObj = ctorInfo->Invoke(args);
1607 else
1608 cliObj = System::Activator::CreateInstance(cliType);
1610 sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
1612 if (comp_td->pBaseTypeDescription)
1614 //convert inherited struct
1615 //cliObj is passed inout (args in_param, out_param are true), hence the passed
1616 // cliObj is used by the callee instead of a newly created struct
1617 map_to_cli(
1618 &cliObj, uno_data,
1619 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, nullptr,
1620 true);
1622 OUString usUnoException("com.sun.star.uno.Exception");
1623 for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
1625 typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
1626 System::String^ sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
1627 sr::FieldInfo^ aField= cliType->GetField(sMemberName);
1628 // special case for Exception.Message. The field has already been
1629 // set while constructing cli object
1630 if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1632 continue;
1634 void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
1635 switch (member_type->eTypeClass)
1637 case typelib_TypeClass_CHAR:
1638 aField->SetValue(cliObj, *(System::Char*) p);
1639 break;
1640 case typelib_TypeClass_BOOLEAN:
1641 aField->SetValue(cliObj, *(System::Boolean*) p);
1642 break;
1643 case typelib_TypeClass_BYTE:
1644 aField->SetValue(cliObj, *(System::Byte*) p);
1645 break;
1646 case typelib_TypeClass_SHORT:
1647 aField->SetValue(cliObj, *(System::Int16*) p);
1648 break;
1649 case typelib_TypeClass_UNSIGNED_SHORT:
1650 aField->SetValue(cliObj, *(System::UInt16*) p);
1651 break;
1652 case typelib_TypeClass_LONG:
1653 aField->SetValue(cliObj, *(System::Int32*) p);
1654 break;
1655 case typelib_TypeClass_UNSIGNED_LONG:
1656 aField->SetValue(cliObj, *(System::UInt32*) p);
1657 break;
1658 case typelib_TypeClass_HYPER:
1659 aField->SetValue(cliObj, *(System::Int64*) p);
1660 break;
1661 case typelib_TypeClass_UNSIGNED_HYPER:
1662 aField->SetValue(cliObj, *(System::UInt64*) p);
1663 break;
1664 case typelib_TypeClass_FLOAT:
1665 aField->SetValue(cliObj, *(System::Single*) p);
1666 break;
1667 case typelib_TypeClass_DOUBLE:
1668 aField->SetValue(cliObj, *(System::Double*) p);
1669 break;
1670 default:
1672 System::Object^ cli_val;
1673 map_to_cli(
1674 &cli_val, p, member_type, nullptr,
1675 false);
1676 aField->SetValue(cliObj, cli_val);
1677 break;
1681 *cli_data= cliObj;
1682 break;
1684 case typelib_TypeClass_SEQUENCE:
1686 sal_Int32 nElements;
1687 uno_Sequence const * seq = 0;
1688 seq = *(uno_Sequence * const *)uno_data;
1689 nElements = seq->nElements;
1691 TypeDescr td( type );
1692 typelib_TypeDescriptionReference * element_type =
1693 ((typelib_IndirectTypeDescription *)td.get())->pType;
1695 switch (element_type->eTypeClass)
1697 case typelib_TypeClass_CHAR:
1699 cli::array<System::Char>^ arChar= gcnew cli::array<System::Char>(nElements);
1700 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arChar, 0, nElements);
1701 *cli_data= arChar;
1702 break;
1704 case typelib_TypeClass_BOOLEAN:
1706 cli::array<System::Byte>^ arBool= gcnew cli::array<System::Byte>(nElements);
1707 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arBool, 0, nElements);
1708 *cli_data= dynamic_cast<cli::array<System::Boolean>^>(arBool);
1709 break;
1711 case typelib_TypeClass_BYTE:
1713 cli::array<System::Byte>^ arByte= gcnew cli::array<System::Byte>(nElements);
1714 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arByte, 0, nElements);
1715 *cli_data= arByte;
1716 break;
1718 case typelib_TypeClass_SHORT:
1720 cli::array<System::Int16>^ arShort= gcnew cli::array<System::Int16>(nElements);
1721 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arShort, 0, nElements);
1722 *cli_data= arShort;
1723 break;
1725 case typelib_TypeClass_UNSIGNED_SHORT:
1727 cli::array<System::UInt16>^ arUInt16= gcnew cli::array<System::UInt16>(nElements);
1728 sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int16>^>(arUInt16),
1729 0, nElements);
1730 *cli_data= arUInt16;
1731 break;
1733 case typelib_TypeClass_LONG:
1735 cli::array<System::Int32>^ arInt32= gcnew cli::array<System::Int32>(nElements);
1736 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt32, 0, nElements);
1737 *cli_data= arInt32;
1738 break;
1740 case typelib_TypeClass_UNSIGNED_LONG:
1742 cli::array<System::UInt32>^ arUInt32= gcnew cli::array<System::UInt32>(nElements);
1743 sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int32>^>(arUInt32),
1744 0, nElements);
1745 *cli_data= arUInt32;
1746 break;
1748 case typelib_TypeClass_HYPER:
1750 cli::array<System::Int64>^ arInt64= gcnew cli::array<System::Int64>(nElements);
1751 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt64, 0, nElements);
1752 *cli_data= arInt64;
1753 break;
1755 //FIXME: Marshal::Copy of UInt64?
1756 case typelib_TypeClass_UNSIGNED_HYPER:
1758 cli::array<System::IntPtr>^ arUInt64= gcnew cli::array<System::IntPtr>(nElements);
1759 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arUInt64, 0, nElements);
1760 *cli_data= dynamic_cast<cli::array<System::UInt64>^>(arUInt64);
1761 break;
1763 case typelib_TypeClass_FLOAT:
1765 cli::array<System::Single>^ arSingle= gcnew cli::array<System::Single>(nElements);
1766 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arSingle, 0, nElements);
1767 *cli_data= arSingle;
1768 break;
1770 case typelib_TypeClass_DOUBLE:
1772 cli::array<System::Double>^ arDouble= gcnew cli::array<System::Double>(nElements);
1773 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arDouble, 0, nElements);
1774 *cli_data= arDouble;
1775 break;
1777 case typelib_TypeClass_STRING:
1779 cli::array<System::String^>^ arString= gcnew cli::array<System::String^>(nElements);
1780 for (int i= 0; i < nElements; i++)
1782 rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
1783 arString[i]= gcnew System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
1785 *cli_data= arString;
1786 break;
1788 case typelib_TypeClass_TYPE:
1790 cli::array<System::Type^>^ arType= gcnew cli::array<System::Type^>(nElements);
1791 for (int i= 0; i < nElements; i++)
1793 arType[i]=
1794 mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
1796 *cli_data= arType;
1797 break;
1799 case typelib_TypeClass_ANY:
1801 cli::array<uno::Any>^ arCli= gcnew cli::array<uno::Any>(nElements);
1802 uno_Any const * p = (uno_Any const *)seq->elements;
1803 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1805 System::Object^ cli_obj = nullptr;
1806 map_to_cli(
1807 &cli_obj, &p[ nPos ], element_type, nullptr, false);
1808 arCli[nPos]= *safe_cast<uno::Any^>(cli_obj);
1810 *cli_data= arCli;
1811 break;
1813 case typelib_TypeClass_ENUM:
1815 //get the Enum type
1816 System::Type^ enumType= nullptr;
1817 if (info != nullptr)
1819 //info is EnumType[]&, remove &
1820 OSL_ASSERT(info->IsByRef);
1821 enumType = info->GetElementType();
1822 //enumType is EnumType[], remove []
1823 enumType = enumType->GetElementType();
1825 else
1826 enumType= mapUnoType(element_type);
1828 System::Array^ arEnum = System::Array::CreateInstance(
1829 enumType, nElements);
1830 for (int i= 0; i < nElements; i++)
1832 arEnum->SetValue(System::Enum::ToObject(enumType,
1833 System::Int32(((sal_Int32*) seq->elements)[i])), i);
1835 *cli_data = arEnum;
1836 break;
1838 case typelib_TypeClass_STRUCT:
1839 case typelib_TypeClass_EXCEPTION:
1841 TypeDescr element_td( element_type );
1842 System::Array^ ar= System::Array::CreateInstance(
1843 mapUnoType(element_type),nElements);
1844 if (0 < nElements)
1846 // ToDo check this
1847 char * p = (char *) &seq->elements;
1848 sal_Int32 nSize = element_td.get()->nSize;
1849 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1851 System::Object^ val;
1852 map_to_cli(
1853 &val, p + (nSize * nPos), element_type, nullptr, false);
1854 ar->SetValue(val, System::Int32(nPos));
1857 *cli_data = ar;
1858 break;
1860 // ToDo, verify
1861 case typelib_TypeClass_SEQUENCE:
1863 System::Array ^ar= System::Array::CreateInstance(
1864 mapUnoType(element_type), nElements);
1865 if (0 < nElements)
1867 TypeDescr element_td( element_type );
1868 uno_Sequence ** elements = (uno_Sequence**) seq->elements;
1869 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1871 System::Object^ val;
1872 map_to_cli(
1873 &val, &elements[nPos], element_type, nullptr, false);
1874 ar->SetValue(val, System::Int32(nPos));
1877 *cli_data = ar;
1878 break;
1880 case typelib_TypeClass_INTERFACE:
1882 TypeDescr element_td( element_type );
1883 System::Type ^ ifaceType= mapUnoType(element_type);
1884 System::Array^ ar= System::Array::CreateInstance(ifaceType, nElements);
1886 char * p = (char *)seq->elements;
1887 sal_Int32 nSize = element_td.get()->nSize;
1888 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1890 System::Object^ val;
1891 map_to_cli(
1892 &val, p + (nSize * nPos), element_type, nullptr, false);
1894 ar->SetValue(val, System::Int32(nPos));
1896 *cli_data= ar;
1897 break;
1899 default:
1901 throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) +
1902 "] unsupported element type: " + OUString::unacquired( &element_type->pTypeName ));
1905 break;
1907 case typelib_TypeClass_INTERFACE:
1909 uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
1910 if (0 != pUnoI)
1912 TypeDescr td( type );
1913 *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
1914 typelib_InterfaceTypeDescription*>(td.get())) ;
1916 else
1917 *cli_data= nullptr;
1918 break;
1920 default:
1922 //ToDo check this exception. The String is probably crippled
1923 throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
1925 } //switch
1926 } // method
1927 } // namespace
1929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */