Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_data.cxx
blob4545538a1f5b08f4310b5e733dce27816d72b96c
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;
45 using namespace std;
47 namespace cli_uno
49 System::String^ mapUnoPolymorphicName(System::String^ unoName);
50 OUString mapCliTypeName(System::String^ typeName);
51 System::String^ mapCliPolymorphicName(System::String^ unoName);
52 System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno);
54 inline unique_ptr< rtl_mem > seq_allocate( sal_Int32 nElements, sal_Int32 nSize )
56 unique_ptr< rtl_mem > seq(
57 rtl_mem::allocate( SAL_SEQUENCE_HEADER_SIZE + (nElements * nSize) ) );
58 uno_Sequence * p = (uno_Sequence *)seq.get();
59 p->nRefCount = 1;
60 p->nElements = nElements;
61 return seq;
64 System::Object^ Bridge::map_uno2cli(uno_Interface * pUnoI, typelib_InterfaceTypeDescription *pTD) const
66 System::Object^ retVal= nullptr;
67 // get oid
68 rtl_uString * pOid = 0;
69 (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI );
70 OSL_ASSERT( 0 != pOid );
71 OUString oid(pOid, SAL_NO_ACQUIRE);
73 // see if the interface was already mapped
74 System::Type^ ifaceType= mapUnoType(reinterpret_cast<typelib_TypeDescription*>(pTD));
75 System::String^ sOid= mapUnoString(oid.pData);
77 System::Threading::Monitor::Enter( CliEnvHolder::g_cli_env );
78 try
80 retVal = CliEnvHolder::g_cli_env->getRegisteredInterface(sOid, ifaceType);
81 if (retVal)
83 // There is already a registered object. It can either be a proxy
84 // for the UNO object or a real cli object. In the first case we
85 // tell the proxy that it shall also represent the current UNO
86 // interface. If it already does that, then it does nothing
87 if (srr::RemotingServices::IsTransparentProxy(retVal))
89 UnoInterfaceProxy^ p = static_cast<UnoInterfaceProxy^>(
90 srr::RemotingServices::GetRealProxy(retVal));
91 p->addUnoInterface(pUnoI, pTD);
94 else
96 retVal = UnoInterfaceProxy::create(
97 (Bridge *) this, pUnoI, pTD, oid );
100 __finally
102 System::Threading::Monitor::Exit( CliEnvHolder::g_cli_env );
105 return retVal;
108 uno_Interface* Bridge::map_cli2uno(System::Object^ cliObj, typelib_TypeDescription *pTD) const
110 uno_Interface* retIface = NULL;
111 // get oid from dot net environment
112 System::String^ ds_oid = CliEnvHolder::g_cli_env->getObjectIdentifier( cliObj);
113 OUString ousOid = mapCliString(ds_oid);
114 // look if interface is already mapped
115 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
116 (typelib_InterfaceTypeDescription*) pTD);
117 if ( ! retIface)
119 System::Threading::Monitor::Enter(Cli_environment::typeid);
122 m_uno_env->getRegisteredInterface(m_uno_env, (void**) &retIface, ousOid.pData,
123 (typelib_InterfaceTypeDescription*) pTD);
124 if ( ! retIface)
126 retIface = CliProxy::create((Bridge*)this, cliObj, pTD, ousOid);
129 __finally
131 System::Threading::Monitor::Exit(Cli_environment::typeid);
134 return retIface;
137 inline System::Type^ loadCliType(rtl_uString * unoName)
139 return loadCliType(mapUnoTypeName(unoName));
142 System::Type^ loadCliType(System::String ^ unoName)
144 System::Type^ retVal= nullptr;
147 //If unoName denotes a polymorphic type, e.g com.sun.star.beans.Defaulted<System.Char>
148 //then we remove the type list, otherwise the type could not be loaded.
149 bool bIsPolymorphic = false;
151 System::String ^ loadName = unoName;
152 int index = unoName->IndexOf('<');
153 if (index != -1)
155 loadName = unoName->Substring(0, index);
156 bIsPolymorphic = true;
158 System::AppDomain^ currentDomain = System::AppDomain::CurrentDomain;
159 cli::array<sr::Assembly^>^ assems = currentDomain->GetAssemblies();
160 for (int i = 0; i < assems->Length; i++)
162 retVal = assems[i]->GetType(loadName, false);
163 if (retVal)
164 break;
167 if (retVal == nullptr)
169 System::String ^ msg = gcnew System::String("A type could not be loaded: ");
170 msg = System::String::Concat(msg, loadName);
171 throw BridgeRuntimeError(mapCliString(msg));
174 if (bIsPolymorphic)
176 retVal = uno::PolymorphicType::GetType(retVal, unoName);
179 catch( System::Exception ^ e)
181 OUString ouMessage(mapCliString(e->Message));
182 throw BridgeRuntimeError(ouMessage);
184 return retVal;
187 System::Type^ mapUnoType(typelib_TypeDescription const * pTD)
189 return mapUnoType(pTD->pWeakRef);
192 System::Type^ mapUnoType(typelib_TypeDescriptionReference const * pTD)
194 System::Type ^ retVal = nullptr;
195 switch (pTD->eTypeClass)
197 case typelib_TypeClass_VOID:
198 retVal= void::typeid; break;
199 case typelib_TypeClass_CHAR:
200 retVal= System::Char::typeid; break;
201 case typelib_TypeClass_BOOLEAN:
202 retVal= System::Boolean::typeid; break;
203 case typelib_TypeClass_BYTE:
204 retVal= System::Byte::typeid; break;
205 case typelib_TypeClass_SHORT:
206 retVal= System::Int16::typeid; break;
207 case typelib_TypeClass_UNSIGNED_SHORT:
208 retVal= System::UInt16::typeid; break;
209 case typelib_TypeClass_LONG:
210 retVal= System::Int32::typeid; break;
211 case typelib_TypeClass_UNSIGNED_LONG:
212 retVal= System::UInt32::typeid; break;
213 case typelib_TypeClass_HYPER:
214 retVal= System::Int64::typeid; break;
215 case typelib_TypeClass_UNSIGNED_HYPER:
216 retVal= System::UInt64::typeid; break;
217 case typelib_TypeClass_FLOAT:
218 retVal= System::Single::typeid; break;
219 case typelib_TypeClass_DOUBLE:
220 retVal= System::Double::typeid; break;
221 case typelib_TypeClass_STRING:
222 retVal= System::String::typeid; break;
223 case typelib_TypeClass_TYPE:
224 retVal= System::Type::typeid; break;
225 case typelib_TypeClass_ANY:
226 retVal= uno::Any::typeid; break;
227 case typelib_TypeClass_ENUM:
228 case typelib_TypeClass_STRUCT:
229 case typelib_TypeClass_EXCEPTION:
230 retVal= loadCliType(pTD->pTypeName); break;
231 case typelib_TypeClass_INTERFACE:
233 //special handling for XInterface, since it does not exist in cli.
234 OUString usXInterface("com.sun.star.uno.XInterface");
235 if (usXInterface.equals(pTD->pTypeName))
236 retVal= System::Object::typeid;
237 else
238 retVal= loadCliType(pTD->pTypeName);
239 break;
241 case typelib_TypeClass_SEQUENCE:
243 css::uno::TypeDescription seqType(
244 const_cast<typelib_TypeDescriptionReference*>(pTD));
245 typelib_TypeDescriptionReference* pElementTDRef=
246 reinterpret_cast<typelib_IndirectTypeDescription*>(seqType.get())->pType;
247 switch (pElementTDRef->eTypeClass)
249 case typelib_TypeClass_CHAR:
250 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArChar)); break;
251 case typelib_TypeClass_BOOLEAN:
252 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArBoolean));
253 break;
254 case typelib_TypeClass_BYTE:
255 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArByte));
256 break;
257 case typelib_TypeClass_SHORT:
258 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt16));
259 break;
260 case typelib_TypeClass_UNSIGNED_SHORT:
261 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt16));
262 break;
263 case typelib_TypeClass_LONG:
264 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt32));
265 break;
266 case typelib_TypeClass_UNSIGNED_LONG:
267 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt32));
268 break;
269 case typelib_TypeClass_HYPER:
270 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArInt64));
271 break;
272 case typelib_TypeClass_UNSIGNED_HYPER:
273 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArUInt64));
274 break;
275 case typelib_TypeClass_FLOAT:
276 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArSingle));
277 break;
278 case typelib_TypeClass_DOUBLE:
279 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArDouble));
280 break;
281 case typelib_TypeClass_STRING:
282 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArString));
283 break;
284 case typelib_TypeClass_TYPE:
285 retVal= System::Type::GetType(const_cast<System::String^>(Constants::sArType));
286 break;
287 case typelib_TypeClass_ANY:
288 case typelib_TypeClass_ENUM:
289 case typelib_TypeClass_EXCEPTION:
290 case typelib_TypeClass_STRUCT:
291 case typelib_TypeClass_INTERFACE:
292 case typelib_TypeClass_SEQUENCE:
294 retVal= loadCliType(pTD->pTypeName);
295 break;
297 default:
298 //All cases should be handled by the case statements above
299 OSL_ASSERT(0);
300 break;
302 break;
304 default:
305 OSL_ASSERT(false);
306 break;
308 return retVal;
311 /** Returns an acquired td.
313 typelib_TypeDescriptionReference* mapCliType(System::Type^ cliType)
315 typelib_TypeDescriptionReference* retVal= NULL;
316 if (cliType == nullptr)
318 retVal = * typelib_static_type_getByTypeClass(
319 typelib_TypeClass_VOID );
320 typelib_typedescriptionreference_acquire( retVal );
321 return retVal;
323 //check for Enum first,
324 //because otherwise case System::TypeCode::Int32 applies
325 if (cliType->IsEnum)
327 OUString usTypeName= mapCliTypeName(cliType->FullName);
328 css::uno::Type unoType(css::uno::TypeClass_ENUM, usTypeName);
329 retVal= unoType.getTypeLibType();
330 typelib_typedescriptionreference_acquire(retVal);
332 else
334 switch (System::Type::GetTypeCode(cliType))
336 case System::TypeCode::Boolean:
337 retVal = * typelib_static_type_getByTypeClass(
338 typelib_TypeClass_BOOLEAN );
339 typelib_typedescriptionreference_acquire( retVal );
340 break;
341 case System::TypeCode::Char:
342 retVal = * typelib_static_type_getByTypeClass(
343 typelib_TypeClass_CHAR );
344 typelib_typedescriptionreference_acquire( retVal );
345 break;
346 case System::TypeCode::Byte:
347 retVal = * typelib_static_type_getByTypeClass(
348 typelib_TypeClass_BYTE );
349 typelib_typedescriptionreference_acquire( retVal );
350 break;
351 case System::TypeCode::Int16:
352 retVal = * typelib_static_type_getByTypeClass(
353 typelib_TypeClass_SHORT );
354 typelib_typedescriptionreference_acquire( retVal );
355 break;
356 case System::TypeCode::Int32:
357 retVal = * typelib_static_type_getByTypeClass(
358 typelib_TypeClass_LONG );
359 typelib_typedescriptionreference_acquire( retVal );
360 break;
361 case System::TypeCode::Int64:
362 retVal = * typelib_static_type_getByTypeClass(
363 typelib_TypeClass_HYPER );
364 typelib_typedescriptionreference_acquire( retVal );
365 break;
366 case System::TypeCode::UInt16:
367 retVal = * typelib_static_type_getByTypeClass(
368 typelib_TypeClass_UNSIGNED_SHORT );
369 typelib_typedescriptionreference_acquire( retVal );
370 break;
371 case System::TypeCode::UInt32:
372 retVal = * typelib_static_type_getByTypeClass(
373 typelib_TypeClass_UNSIGNED_LONG );
374 typelib_typedescriptionreference_acquire( retVal );
375 break;
376 case System::TypeCode::UInt64:
377 retVal = * typelib_static_type_getByTypeClass(
378 typelib_TypeClass_UNSIGNED_HYPER );
379 typelib_typedescriptionreference_acquire( retVal );
380 break;
381 case System::TypeCode::Single:
382 retVal = * typelib_static_type_getByTypeClass(
383 typelib_TypeClass_FLOAT );
384 typelib_typedescriptionreference_acquire( retVal );
385 break;
386 case System::TypeCode::Double:
387 retVal = * typelib_static_type_getByTypeClass(
388 typelib_TypeClass_DOUBLE );
389 typelib_typedescriptionreference_acquire( retVal );
390 break;
391 case System::TypeCode::String:
392 retVal = * typelib_static_type_getByTypeClass(
393 typelib_TypeClass_STRING );
394 typelib_typedescriptionreference_acquire( retVal );
395 break;
396 default:
397 break;
400 if (retVal == NULL)
402 System::String^ cliTypeName= cliType->FullName;
403 // Void
404 if (const_cast<System::String^>(Constants::sVoid)->Equals(
405 cliTypeName))
407 retVal = * typelib_static_type_getByTypeClass(
408 typelib_TypeClass_VOID );
409 typelib_typedescriptionreference_acquire( retVal );
411 // Type
412 else if (const_cast<System::String^>(Constants::sType)->Equals(
413 cliTypeName))
415 retVal = * typelib_static_type_getByTypeClass(
416 typelib_TypeClass_TYPE );
417 typelib_typedescriptionreference_acquire( retVal );
419 // Any
420 else if (const_cast<System::String^>(Constants::sAny)->Equals(
421 cliTypeName))
423 retVal = * typelib_static_type_getByTypeClass(
424 typelib_TypeClass_ANY );
425 typelib_typedescriptionreference_acquire( retVal );
427 //struct, interfaces, sequences
428 else
430 OUString usTypeName;
431 uno::PolymorphicType ^ poly = dynamic_cast<uno::PolymorphicType^>(cliType);
432 if (poly != nullptr)
433 usTypeName = mapCliTypeName( poly->PolymorphicName);
434 else
435 usTypeName = mapCliTypeName(cliTypeName);
436 typelib_TypeDescription* td = NULL;
437 typelib_typedescription_getByName(&td, usTypeName.pData);
438 if (td)
440 retVal = td->pWeakRef;
441 typelib_typedescriptionreference_acquire(retVal);
442 typelib_typedescription_release(td);
446 if (retVal == NULL)
448 throw BridgeRuntimeError("[cli_uno bridge] mapCliType():could not map type: " + mapCliString(cliType->FullName));
450 return retVal;
454 Otherwise a leading "unoidl." is removed.
456 System::String^ mapUnoTypeName(rtl_uString const * typeName)
458 OUString usUnoName( const_cast< rtl_uString * >( typeName ) );
459 st::StringBuilder^ buf= gcnew st::StringBuilder();
460 //determine if the type is a sequence and its dimensions
461 int dims= 0;
462 if (usUnoName[0] == '[')
464 sal_Int32 index= 1;
465 while (true)
467 if (usUnoName[index++] == ']')
468 dims++;
469 if (usUnoName[index++] != '[')
470 break;
472 usUnoName = usUnoName.copy(index - 1);
474 System::String ^ sUnoName = mapUnoString(usUnoName.pData);
475 if (sUnoName->Equals(const_cast<System::String^>(Constants::usBool)))
476 buf->Append(const_cast<System::String^>(Constants::sBoolean));
477 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usChar)))
478 buf->Append(const_cast<System::String^>(Constants::sChar));
479 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usByte)))
480 buf->Append(const_cast<System::String^>(Constants::sByte));
481 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usShort)))
482 buf->Append(const_cast<System::String^>(Constants::sInt16));
483 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUShort)))
484 buf->Append(const_cast<System::String^>(Constants::sUInt16));
485 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usLong)))
486 buf->Append(const_cast<System::String^>(Constants::sInt32));
487 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usULong)))
488 buf->Append(const_cast<System::String^>(Constants::sUInt32));
489 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usHyper)))
490 buf->Append(const_cast<System::String^>(Constants::sInt64));
491 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usUHyper)))
492 buf->Append(const_cast<System::String^>(Constants::sUInt64));
493 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usFloat)))
494 buf->Append(const_cast<System::String^>(Constants::sSingle));
495 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usDouble)))
496 buf->Append(const_cast<System::String^>(Constants::sDouble));
497 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usString)))
498 buf->Append(const_cast<System::String^>(Constants::sString));
499 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usVoid)))
500 buf->Append(const_cast<System::String^>(Constants::sVoid));
501 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usType)))
502 buf->Append(const_cast<System::String^>(Constants::sType));
503 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usXInterface)))
504 buf->Append(const_cast<System::String^>(Constants::sObject));
505 else if (sUnoName->Equals(const_cast<System::String^>(Constants::usAny)))
507 buf->Append(const_cast<System::String^>(Constants::sAny));
509 else
511 //put "unoidl." at the beginning
512 buf->Append(const_cast<System::String^>(Constants::sUnoidl));
513 //for polymorphic struct types remove the brackets, e.g mystruct<bool> -> mystruct
514 System::String ^ sName = mapUnoPolymorphicName(sUnoName);
515 buf->Append(sName);
517 // append []
518 for (;dims--;)
519 buf->Append(const_cast<System::String^>(Constants::sBrackets));
521 return buf->ToString();
524 /** For example, there is a uno type
525 com.sun.star.Foo<char, long>.
526 The values in the type list
527 are uno types and are replaced by cli types, such as System.Char,
528 System.Int32, etc.
529 The prefix unoidl is not added.
531 inline System::String^ mapUnoPolymorphicName(System::String^ unoName)
533 return mapPolymorphicName(unoName, false);
536 /** For example, there is a type name such as
537 com.sun.star.Foo<System.Char, System.Int32>.
538 The values in the type list
539 are CLI types and are replaced by uno types, such as char,
540 long, etc.
541 The prefix unoidl remains.
543 inline System::String^ mapCliPolymorphicName(System::String^ unoName)
545 return mapPolymorphicName(unoName, true);
548 System::String^ mapPolymorphicName(System::String^ unoName, bool bCliToUno)
550 int index = unoName->IndexOf('<');
551 if (index == -1)
552 return unoName;
554 System::Text::StringBuilder ^ builder = gcnew System::Text::StringBuilder(256);
555 builder->Append(unoName->Substring(0, index +1 ));
557 //Find the first occurrence of ','
558 //If the parameter is a polymorphic struct then we need to ignore everything
559 //between the brackets because it can also contain commas
560 //get the type list within < and >
561 int endIndex = unoName->Length - 1;
562 index++;
563 int cur = index;
564 int countParams = 0;
565 while (cur <= endIndex)
567 System::Char c = unoName[cur];
568 if (c == ',' || c == '>')
570 //insert a comma if needed
571 if (countParams != 0)
572 builder->Append(",");
573 countParams++;
574 System::String ^ sParam = unoName->Substring(index, cur - index);
575 //skip the comma
576 cur++;
577 //the index to the beginning of the next param
578 index = cur;
579 if (bCliToUno)
581 builder->Append(mapCliTypeName(sParam).getStr());
583 else
585 OUString s = mapCliString(sParam);
586 builder->Append(mapUnoTypeName(s.pData));
589 else if (c == '<')
591 cur++;
592 //continue until the matching '>'
593 int numNested = 0;
594 for (;;cur++)
596 System::Char curChar = unoName[cur];
597 if (curChar == '<')
599 numNested ++;
601 else if (curChar == '>')
603 if (numNested > 0)
604 numNested--;
605 else
606 break;
610 cur++;
613 builder->Append((System::Char) '>');
614 return builder->ToString();
617 OUString mapCliTypeName(System::String^ typeName)
619 int dims= 0;
620 // Array? determine the "rank" (number of "[]")
621 // move from the rightmost end to the left, for example
622 // unoidl.PolymorphicStruct<System.Char[]>[]
623 // has only a "dimension" of 1
624 int cur = typeName->Length - 1;
625 bool bRightBracket = false;
626 while (cur >= 0)
628 System::Char c = typeName[cur];
629 if (c == ']')
631 bRightBracket = true;
633 else if (c == '[')
635 if (!bRightBracket)
636 throw BridgeRuntimeError(
637 "Typename is wrong. No matching brackets for sequence. Name is: " +
638 mapCliString(typeName));
639 bRightBracket = false;
640 dims ++;
642 else
644 if (bRightBracket)
645 throw BridgeRuntimeError(
646 "Typename is wrong. No matching brackets for sequence. Name is: " +
647 mapCliString(typeName));
648 break;
650 cur--;
653 if (bRightBracket || cur < 0)
654 throw BridgeRuntimeError(
655 "Typename is wrong. " +
656 mapCliString(typeName));
658 typeName = typeName->Substring(0, cur + 1);
660 System::Text::StringBuilder ^ buf = gcnew System::Text::StringBuilder(512);
662 //Put the "[]" at the beginning of the uno type name
663 for (;dims--;)
664 buf->Append(const_cast<System::String^>(Constants::usBrackets));
666 if (typeName->Equals(const_cast<System::String^>(Constants::sBoolean)))
667 buf->Append(const_cast<System::String^>(Constants::usBool));
668 else if (typeName->Equals(const_cast<System::String^>(Constants::sChar)))
669 buf->Append(const_cast<System::String^>(Constants::usChar));
670 else if (typeName->Equals(const_cast<System::String^>(Constants::sByte)))
671 buf->Append(const_cast<System::String^>(Constants::usByte));
672 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt16)))
673 buf->Append(const_cast<System::String^>(Constants::usShort));
674 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt16)))
675 buf->Append(const_cast<System::String^>(Constants::usUShort));
676 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt32)))
677 buf->Append(const_cast<System::String^>(Constants::usLong));
678 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt32)))
679 buf->Append(const_cast<System::String^>(Constants::usULong));
680 else if (typeName->Equals(const_cast<System::String^>(Constants::sInt64)))
681 buf->Append(const_cast<System::String^>(Constants::usHyper));
682 else if (typeName->Equals(const_cast<System::String^>(Constants::sUInt64)))
683 buf->Append(const_cast<System::String^>(Constants::usUHyper));
684 else if (typeName->Equals(const_cast<System::String^>(Constants::sSingle)))
685 buf->Append(const_cast<System::String^>(Constants::usFloat));
686 else if (typeName->Equals(const_cast<System::String^>(Constants::sDouble)))
687 buf->Append(const_cast<System::String^>(Constants::usDouble));
688 else if (typeName->Equals(const_cast<System::String^>(Constants::sString)))
689 buf->Append(const_cast<System::String^>(Constants::usString));
690 else if (typeName->Equals(const_cast<System::String^>(Constants::sVoid)))
691 buf->Append(const_cast<System::String^>(Constants::usVoid));
692 else if (typeName->Equals(const_cast<System::String^>(Constants::sType)))
693 buf->Append(const_cast<System::String^>(Constants::usType));
694 else if (typeName->Equals(const_cast<System::String^>(Constants::sObject)))
695 buf->Append(const_cast<System::String^>(Constants::usXInterface));
696 else if (typeName->Equals(const_cast<System::String^>(Constants::sAny)))
697 buf->Append(const_cast<System::String^>(Constants::usAny));
698 else
700 System::String ^ sName = mapCliPolymorphicName(typeName);
701 int i= sName->IndexOf(L'.');
702 buf->Append(sName->Substring(i + 1));
704 return mapCliString(buf->ToString());
707 /** Maps uno types to dot net types.
708 * If uno_data is null then the type description is converted to System::Type
710 inline System::String^ mapUnoString( rtl_uString const * data)
712 OSL_ASSERT(data);
713 return gcnew System::String((__wchar_t*) data->buffer, 0, data->length);
716 OUString mapCliString(System::String ^ data)
719 if (data != nullptr)
721 static_assert(sizeof(wchar_t) == sizeof(sal_Unicode), "char mismatch");
722 pin_ptr<wchar_t const> pdata= PtrToStringChars(data);
723 return OUString(
724 reinterpret_cast<sal_Unicode const *>(pdata),
725 const_cast<System::String^>(data)->Length);
727 else
729 return OUString();
733 // ToDo convert cli types to expected types, e.g a long to a short where the uno type
734 // is a sal_Int16. This could be necessary if a scripting language (typeless) is used
735 // @param assign the uno_data has to be destructed (in/out args)
736 void Bridge::map_to_uno(void * uno_data, System::Object^ cli_data,
737 typelib_TypeDescriptionReference * type,
738 bool assign) const
740 try{
741 switch (type->eTypeClass)
743 case typelib_TypeClass_VOID:
744 break;
745 case typelib_TypeClass_CHAR:
747 System::Char aChar= *safe_cast<System::Char^>(cli_data);
748 *(sal_Unicode*) uno_data= aChar;
749 break;
751 case typelib_TypeClass_BOOLEAN:
753 System::Boolean aBool= *safe_cast<System::Boolean^>(cli_data);
754 *(sal_Bool*)uno_data= aBool == true ? sal_True : sal_False;
755 break;
757 case typelib_TypeClass_BYTE:
759 System::Byte aByte= *safe_cast<System::Byte^>(cli_data);
760 *(sal_Int8*) uno_data= aByte;
761 break;
763 case typelib_TypeClass_SHORT:
765 System::Int16 aShort= *safe_cast<System::Int16^>(cli_data);
766 *(sal_Int16*) uno_data= aShort;
767 break;
769 case typelib_TypeClass_UNSIGNED_SHORT:
771 System::UInt16 aUShort= *safe_cast<System::UInt16^>(cli_data);
772 *(sal_uInt16*) uno_data= aUShort;
773 break;
775 case typelib_TypeClass_LONG:
777 System::Int32 aLong= *safe_cast<System::Int32^>(cli_data);
778 *(sal_Int32*) uno_data= aLong;
779 break;
781 case typelib_TypeClass_UNSIGNED_LONG:
783 System::UInt32 aULong= *safe_cast<System::UInt32^>(cli_data);
784 *(sal_uInt32*) uno_data= aULong;
785 break;
787 case typelib_TypeClass_HYPER:
789 System::Int64 aHyper= *safe_cast<System::Int64^>(cli_data);
790 *(sal_Int64*) uno_data= aHyper;
791 break;
793 case typelib_TypeClass_UNSIGNED_HYPER:
795 System::UInt64 aLong= *safe_cast<System::UInt64^>(cli_data);
796 *(sal_uInt64*) uno_data= aLong;
797 break;
799 case typelib_TypeClass_FLOAT:
801 System::Single aFloat= *safe_cast<System::Single^>(cli_data);
802 *(float*) uno_data= aFloat;
803 break;
805 case typelib_TypeClass_DOUBLE:
807 System::Double aDouble= *safe_cast<System::Double^>(cli_data);
808 *(double*) uno_data= aDouble;
809 break;
811 case typelib_TypeClass_STRING:
813 if (assign && *(rtl_uString**) uno_data)
814 rtl_uString_release(*(rtl_uString**) uno_data);
816 *(rtl_uString **)uno_data = 0;
817 if (cli_data == nullptr)
819 rtl_uString_new((rtl_uString**) uno_data);
821 else
823 System::String ^s= safe_cast<System::String^>(cli_data);
824 pin_ptr<const wchar_t> pdata= PtrToStringChars(s);
825 rtl_uString_newFromStr_WithLength(
826 reinterpret_cast<rtl_uString **>(uno_data),
827 reinterpret_cast<sal_Unicode const *>(pdata), s->Length);
829 break;
831 case typelib_TypeClass_TYPE:
833 typelib_TypeDescriptionReference* td= mapCliType(safe_cast<System::Type^>(
834 cli_data));
835 if (assign)
837 typelib_typedescriptionreference_release(
838 *(typelib_TypeDescriptionReference **)uno_data );
840 *(typelib_TypeDescriptionReference **)uno_data = td;
841 break;
843 case typelib_TypeClass_ANY:
845 uno_Any * pAny = (uno_Any *)uno_data;
846 if (cli_data == nullptr) // null-ref or uninitialized any maps to empty any
848 if (assign)
849 uno_any_destruct( pAny, 0 );
850 uno_any_construct( pAny, 0, 0, 0 );
851 break;
853 uno::Any aAny= *safe_cast<uno::Any^>(cli_data);
854 css::uno::Type value_td( mapCliType(aAny.Type), SAL_NO_ACQUIRE);
856 if (assign)
857 uno_any_destruct( pAny, 0 );
861 switch (value_td.getTypeClass())
863 case typelib_TypeClass_VOID:
864 pAny->pData = &pAny->pReserved;
865 break;
866 case typelib_TypeClass_CHAR:
867 pAny->pData = &pAny->pReserved;
868 *(sal_Unicode*) &pAny->pReserved = *safe_cast<System::Char^>(aAny.Value);
869 break;
870 case typelib_TypeClass_BOOLEAN:
871 pAny->pData = &pAny->pReserved;
872 *(sal_Bool *) &pAny->pReserved = *safe_cast<System::Boolean^>(aAny.Value);
873 break;
874 case typelib_TypeClass_BYTE:
875 pAny->pData = &pAny->pReserved;
876 *(sal_Int8*) &pAny->pReserved = *safe_cast<System::Byte^>(aAny.Value);
877 break;
878 case typelib_TypeClass_SHORT:
879 pAny->pData = &pAny->pReserved;
880 *(sal_Int16*) &pAny->pReserved = *safe_cast<System::Int16^>(aAny.Value);
881 break;
882 case typelib_TypeClass_UNSIGNED_SHORT:
883 pAny->pData = &pAny->pReserved;
884 *(sal_uInt16*) &pAny->pReserved = *safe_cast<System::UInt16^>(aAny.Value);
885 break;
886 case typelib_TypeClass_LONG:
887 pAny->pData = &pAny->pReserved;
888 *(sal_Int32*) &pAny->pReserved = *safe_cast<System::Int32^>(aAny.Value);
889 break;
890 case typelib_TypeClass_UNSIGNED_LONG:
891 pAny->pData = &pAny->pReserved;
892 *(sal_uInt32*) &pAny->pReserved = *safe_cast<System::UInt32^>(aAny.Value);
893 break;
894 case typelib_TypeClass_HYPER:
895 if (sizeof (sal_Int64) <= sizeof (void *))
897 pAny->pData = &pAny->pReserved;
898 *(sal_Int64*) &pAny->pReserved = *safe_cast<System::Int64^>(aAny.Value);
900 else
902 unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_Int64) ) );
903 *(sal_Int64 *) mem.get()= *safe_cast<System::Int64^>(aAny.Value);
904 pAny->pData = mem.release();
906 break;
907 case typelib_TypeClass_UNSIGNED_HYPER:
908 if (sizeof (sal_uInt64) <= sizeof (void *))
910 pAny->pData = &pAny->pReserved;
911 *(sal_uInt64*) &pAny->pReserved = *safe_cast<System::UInt64^>(aAny.Value);
913 else
915 unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (sal_uInt64) ) );
916 *(sal_uInt64 *) mem.get()= *safe_cast<System::UInt64^>(aAny.Value);
917 pAny->pData = mem.release();
919 break;
920 case typelib_TypeClass_FLOAT:
921 if (sizeof (float) <= sizeof (void *))
923 pAny->pData = &pAny->pReserved;
924 *(float*) &pAny->pReserved = *safe_cast<System::Single^>(aAny.Value);
926 else
928 unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (float) ) );
929 *(float*) mem.get() = *safe_cast<System::Single^>(aAny.Value);
930 pAny->pData = mem.release();
932 break;
933 case typelib_TypeClass_DOUBLE:
934 if (sizeof (double) <= sizeof (void *))
936 pAny->pData = &pAny->pReserved;
937 *(double*) &pAny->pReserved= *safe_cast<System::Double^>(aAny.Value);
939 else
941 unique_ptr< rtl_mem > mem( rtl_mem::allocate( sizeof (double) ) );
942 *(double*) mem.get()= *safe_cast<System::Double^>(aAny.Value);
943 pAny->pData= mem.release();
945 break;
946 case typelib_TypeClass_STRING: // anies often contain strings; copy string directly
948 pAny->pData= &pAny->pReserved;
949 OUString _s = mapCliString(static_cast<System::String^>(aAny.Value));
950 pAny->pReserved= _s.pData;
951 rtl_uString_acquire(_s.pData);
952 break;
954 case typelib_TypeClass_TYPE:
955 case typelib_TypeClass_ENUM: //ToDo copy enum direct
956 case typelib_TypeClass_SEQUENCE:
957 case typelib_TypeClass_INTERFACE:
958 pAny->pData = &pAny->pReserved;
959 pAny->pReserved = 0;
960 map_to_uno(
961 &pAny->pReserved, aAny.Value, value_td.getTypeLibType(),
962 false /* no assign */);
963 break;
964 case typelib_TypeClass_STRUCT:
965 case typelib_TypeClass_EXCEPTION:
967 css::uno::Type anyType(value_td);
968 typelib_TypeDescription* td= NULL;
969 anyType.getDescription(&td);
970 unique_ptr< rtl_mem > mem(rtl_mem::allocate(td->nSize));
971 typelib_typedescription_release(td);
972 map_to_uno(
973 mem.get(), aAny.Value, value_td.getTypeLibType(),
974 false /* no assign */);
975 pAny->pData = mem.release();
976 break;
978 default:
980 throw BridgeRuntimeError("[map_to_uno():" + value_td.getTypeName() + "] unsupported value type of any!");
984 catch(System::InvalidCastException^ )
986 // ToDo check this
987 if (assign)
988 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
989 OUString str = "[map_to_uno():Any" + value_td.getTypeName() + "]The Any type " + value_td.getTypeName() + " does not correspond to its value type: ";
990 if(aAny.Value != nullptr)
992 css::uno::Type td(mapCliType(aAny.Value->GetType()), SAL_NO_ACQUIRE);
993 str += td.getTypeName();
995 if (assign)
996 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
997 throw BridgeRuntimeError(str);
999 catch (BridgeRuntimeError& )
1001 if (assign)
1002 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1003 throw;
1005 catch (...)
1007 if (assign)
1008 uno_any_construct( pAny, 0, 0, 0 ); // restore some valid any
1009 throw;
1012 pAny->pType = value_td.getTypeLibType();
1013 typelib_typedescriptionreference_acquire(pAny->pType);
1014 break;
1016 case typelib_TypeClass_ENUM:
1018 // InvalidCastException is caught at the end of this method
1019 System::Int32 aEnum= System::Convert::ToInt32((cli_data));
1020 *(sal_Int32*) uno_data = aEnum;
1021 break;
1023 case typelib_TypeClass_STRUCT:
1024 case typelib_TypeClass_EXCEPTION:
1026 css::uno::TypeDescription td(type);
1027 typelib_CompoundTypeDescription * comp_td =
1028 (typelib_CompoundTypeDescription*) td.get();
1030 typelib_StructTypeDescription * struct_td = NULL;
1031 if (type->eTypeClass == typelib_TypeClass_STRUCT)
1032 struct_td = (typelib_StructTypeDescription*) td.get();
1034 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1035 ::typelib_typedescription_complete(
1036 (typelib_TypeDescription**) & comp_td );
1038 sal_Int32 nMembers = comp_td->nMembers;
1039 boolean bException= false;
1040 System::Type^ cliType = nullptr;
1041 if (cli_data)
1042 cliType = cli_data->GetType();
1044 if (0 != comp_td->pBaseTypeDescription)
1046 map_to_uno(
1047 uno_data, cli_data,
1048 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef,
1049 assign);
1051 sal_Int32 nPos = 0;
1054 OUString usUnoException("com.sun.star.uno.Exception");
1055 for (; nPos < nMembers; ++nPos)
1057 typelib_TypeDescriptionReference * member_type= comp_td->ppTypeRefs[nPos];
1058 System::Object^ val= nullptr;
1059 if (cli_data != nullptr)
1061 sr::FieldInfo^ aField= cliType->GetField(
1062 mapUnoString(comp_td->ppMemberNames[nPos]));
1063 // special case for Exception.Message property
1064 // The com.sun.star.uno.Exception.Message field is mapped to the
1065 // System.Exception property. Type.GetField("Message") returns null
1066 if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1067 {// get Exception.Message property
1068 OUString usMessageMember("Message");
1069 if (usMessageMember.equals(comp_td->ppMemberNames[nPos]))
1071 sr::PropertyInfo^ pi= cliType->GetProperty(
1072 mapUnoString(comp_td->ppMemberNames[nPos]));
1073 val= pi->GetValue(cli_data, nullptr);
1075 else
1077 throw BridgeRuntimeError("[map_to_uno(): Member: " + OUString::unacquired(&comp_td->ppMemberNames[nPos]));
1080 else
1082 val= aField->GetValue(cli_data);
1085 void * p = (char *) uno_data + comp_td->pMemberOffsets[ nPos ];
1086 //When using polymorphic structs then the parameterized members can be null.
1087 //Then we set a default value.
1088 bool bDefault = (struct_td != NULL
1089 && struct_td->pParameterizedTypes != NULL
1090 && struct_td->pParameterizedTypes[nPos] == sal_True
1091 && val == nullptr)
1092 || cli_data == nullptr;
1093 switch (member_type->eTypeClass)
1095 case typelib_TypeClass_CHAR:
1096 if (bDefault)
1097 *(sal_Unicode*) p = 0;
1098 else
1099 *(sal_Unicode*) p = *safe_cast<System::Char^>(val);
1100 break;
1101 case typelib_TypeClass_BOOLEAN:
1102 if (bDefault)
1103 *(sal_Bool*) p = sal_False;
1104 else
1105 *(sal_Bool*) p = *safe_cast<System::Boolean^>(val);
1106 break;
1107 case typelib_TypeClass_BYTE:
1108 if (bDefault)
1109 *(sal_Int8*) p = 0;
1110 else
1111 *(sal_Int8*) p = *safe_cast<System::Byte^>(val);
1112 break;
1113 case typelib_TypeClass_SHORT:
1114 if (bDefault)
1115 *(sal_Int16*) p = 0;
1116 else
1117 *(sal_Int16*) p = *safe_cast<System::Int16^>(val);
1118 break;
1119 case typelib_TypeClass_UNSIGNED_SHORT:
1120 if (bDefault)
1121 *(sal_uInt16*) p = 0;
1122 else
1123 *(sal_uInt16*) p = *safe_cast<System::UInt16^>(val);
1124 break;
1125 case typelib_TypeClass_LONG:
1126 if (bDefault)
1127 *(sal_Int32*) p = 0;
1128 else
1129 *(sal_Int32*) p = *safe_cast<System::Int32^>(val);
1130 break;
1131 case typelib_TypeClass_UNSIGNED_LONG:
1132 if (bDefault)
1133 *(sal_uInt32*) p = 0;
1134 else
1135 *(sal_uInt32*) p = *safe_cast<System::UInt32^>(val);
1136 break;
1137 case typelib_TypeClass_HYPER:
1138 if (bDefault)
1139 *(sal_Int64*) p = 0;
1140 else
1141 *(sal_Int64*) p = *safe_cast<System::Int64^>(val);
1142 break;
1143 case typelib_TypeClass_UNSIGNED_HYPER:
1144 if (bDefault)
1145 *(sal_uInt64*) p = 0;
1146 else
1147 *(sal_uInt64*) p= *safe_cast<System::UInt64^>(val);
1148 break;
1149 case typelib_TypeClass_FLOAT:
1150 if (bDefault)
1151 *(float*) p = 0.;
1152 else
1153 *(float*) p = *safe_cast<System::Single^>(val);
1154 break;
1155 case typelib_TypeClass_DOUBLE:
1156 if (bDefault)
1157 *(double*) p = 0.;
1158 else
1159 *(double*) p = *safe_cast<System::Double^>(val);
1160 break;
1161 default:
1162 { // ToDo enum, should be converted here
1163 map_to_uno(p, val, member_type, assign);
1164 break;
1169 catch (BridgeRuntimeError& e)
1171 bException= true;
1172 OUString str = "[map_to_uno():";
1173 if (cliType)
1175 str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]) + " ";
1177 str += e.m_message;
1178 throw BridgeRuntimeError(str);
1180 catch (System::InvalidCastException^ )
1182 bException= true;
1183 OUString str = "[map_to_uno():";
1184 if (cliType)
1186 str += mapCliString(cliType->FullName) + "." + OUString::unacquired(&comp_td->ppMemberNames[nPos]);
1188 str += "] Value has not the required type.";
1189 throw BridgeRuntimeError(str);
1191 catch (...)
1193 OSL_ASSERT(0);
1194 bException= true;
1195 throw;
1197 __finally
1199 if (bException && !assign) // if assign then caller cleans up
1201 // cleanup the members which we have converted so far
1202 for ( sal_Int32 nCleanup = 0; nCleanup < nPos; ++nCleanup )
1204 uno_type_destructData(
1205 uno_data, comp_td->ppTypeRefs[ nCleanup ], 0 );
1207 if (0 != comp_td->pBaseTypeDescription)
1209 uno_destructData(
1210 uno_data, (typelib_TypeDescription *)comp_td->pBaseTypeDescription, 0 );
1214 break;
1216 case typelib_TypeClass_SEQUENCE:
1218 TypeDescr td( type );
1219 typelib_TypeDescriptionReference * element_type =
1220 ((typelib_IndirectTypeDescription *)td.get())->pType;
1222 unique_ptr< rtl_mem > seq;
1224 System::Array^ ar = nullptr;
1225 if (cli_data != nullptr)
1227 ar = safe_cast<System::Array^>(cli_data);
1228 sal_Int32 nElements = ar->GetLength(0);
1232 switch (element_type->eTypeClass)
1234 case typelib_TypeClass_CHAR:
1235 seq = seq_allocate(nElements, sizeof (sal_Unicode));
1236 sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
1237 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1238 break;
1239 case typelib_TypeClass_BOOLEAN:
1240 seq = seq_allocate(nElements, sizeof (sal_Bool));
1241 sri::Marshal::Copy(safe_cast<cli::array<System::Char>^>(cli_data), 0,
1242 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1243 break;
1244 case typelib_TypeClass_BYTE:
1245 seq = seq_allocate( nElements, sizeof (sal_Int8) );
1246 sri::Marshal::Copy(safe_cast<cli::array<System::Byte>^>(cli_data), 0,
1247 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1248 break;
1249 case typelib_TypeClass_SHORT:
1250 seq = seq_allocate(nElements, sizeof (sal_Int16));
1251 sri::Marshal::Copy(safe_cast<cli::array<System::Int16>^>(cli_data), 0,
1252 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1253 break;
1254 case typelib_TypeClass_UNSIGNED_SHORT:
1255 seq = seq_allocate( nElements, sizeof (sal_uInt16) );
1256 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int16>^>(
1257 safe_cast<cli::array<System::UInt16>^>(cli_data)), 0,
1258 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1259 break;
1260 case typelib_TypeClass_LONG:
1261 seq = seq_allocate(nElements, sizeof (sal_Int32));
1262 sri::Marshal::Copy(safe_cast<cli::array<System::Int32>^>(cli_data), 0,
1263 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1264 break;
1265 case typelib_TypeClass_UNSIGNED_LONG:
1266 seq = seq_allocate( nElements, sizeof (sal_uInt32) );
1267 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int32>^>(
1268 safe_cast<cli::array<System::UInt32>^>(cli_data)), 0,
1269 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1270 break;
1271 case typelib_TypeClass_HYPER:
1272 seq = seq_allocate(nElements, sizeof (sal_Int64));
1273 sri::Marshal::Copy(safe_cast<cli::array<System::Int64>^>(cli_data), 0,
1274 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1275 break;
1276 case typelib_TypeClass_UNSIGNED_HYPER:
1277 seq = seq_allocate(nElements, sizeof (sal_uInt64));
1278 sri::Marshal::Copy(dynamic_cast<cli::array<System::Int64>^>(
1279 safe_cast<cli::array<System::UInt64>^>(cli_data)), 0,
1280 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1281 break;
1282 case typelib_TypeClass_FLOAT:
1283 seq = seq_allocate(nElements, sizeof (float));
1284 sri::Marshal::Copy(safe_cast<cli::array<System::Single>^>(cli_data), 0,
1285 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1286 break;
1287 case typelib_TypeClass_DOUBLE:
1288 seq = seq_allocate(nElements, sizeof (double));
1289 sri::Marshal::Copy(safe_cast<cli::array<System::Double>^>(cli_data), 0,
1290 IntPtr(& ((uno_Sequence*) seq.get())->elements), nElements);
1291 break;
1292 case typelib_TypeClass_STRING:
1294 seq = seq_allocate(nElements, sizeof (rtl_uString*));
1295 cli::array<System::String^>^ arStr= safe_cast<cli::array<System::String^>^>(cli_data);
1296 for (int i= 0; i < nElements; i++)
1298 pin_ptr<const wchar_t> pdata= PtrToStringChars(arStr[i]);
1299 rtl_uString** pStr= & ((rtl_uString**) &
1300 ((uno_Sequence*) seq.get())->elements)[i];
1301 *pStr= NULL;
1302 rtl_uString_newFromStr_WithLength(
1303 pStr,
1304 reinterpret_cast<sal_Unicode const *>(pdata),
1305 arStr[i]->Length);
1307 break;
1309 case typelib_TypeClass_ENUM:
1310 seq = seq_allocate(nElements, sizeof (sal_Int32));
1311 for (int i= 0; i < nElements; i++)
1313 ((sal_Int32*) &((uno_Sequence*) seq.get())->elements)[i]=
1314 System::Convert::ToInt32(ar->GetValue(i));
1316 break;
1317 case typelib_TypeClass_TYPE:
1318 case typelib_TypeClass_ANY:
1319 case typelib_TypeClass_STRUCT:
1320 case typelib_TypeClass_EXCEPTION:
1321 case typelib_TypeClass_SEQUENCE:
1322 case typelib_TypeClass_INTERFACE:
1324 TypeDescr element_td( element_type );
1325 seq = seq_allocate( nElements, element_td.get()->nSize );
1327 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos)
1331 void * p= ((uno_Sequence *) seq.get())->elements +
1332 (nPos * element_td.get()->nSize);
1333 System::Object^ elemData= safe_cast<System::Array^>(cli_data)->GetValue(nPos);
1334 map_to_uno(
1335 p, elemData, element_td.get()->pWeakRef,
1336 false /* no assign */);
1338 catch (...)
1340 // cleanup
1341 for ( sal_Int32 nCleanPos = 0; nCleanPos < nPos; ++nCleanPos )
1343 void * p =
1344 ((uno_Sequence *)seq.get())->elements +
1345 (nCleanPos * element_td.get()->nSize);
1346 uno_destructData( p, element_td.get(), 0 );
1348 throw;
1351 break;
1353 default:
1355 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) +
1356 "] unsupported sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
1360 catch (BridgeRuntimeError& e)
1362 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] conversion failed\n " + e.m_message);
1364 catch (System::InvalidCastException^ )
1366 // Ok, checked
1367 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName) +
1368 "] could not convert sequence element type: " + OUString::unacquired( &element_type->pTypeName ));
1370 catch (...)
1372 OSL_ASSERT(0);
1373 throw;
1375 __finally
1377 if (assign)
1378 uno_destructData( uno_data, td.get(), 0 );
1381 else
1383 seq = seq_allocate(0, sizeof (sal_Int32));
1385 *(uno_Sequence **)uno_data = (uno_Sequence *)seq.release();
1386 break;
1388 case typelib_TypeClass_INTERFACE:
1390 if (assign)
1392 uno_Interface * p = *(uno_Interface **)uno_data;
1393 if (0 != p)
1394 (*p->release)( p );
1396 if (nullptr == cli_data) // null-ref
1398 *(uno_Interface **)uno_data = 0;
1400 else
1402 TypeDescr td( type );
1403 uno_Interface * pUnoI = map_cli2uno(cli_data, td.get());
1404 *(uno_Interface **)uno_data = pUnoI;
1406 break;
1408 default:
1410 //ToDo check
1411 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
1415 // BridgeRuntimeError are allowed to be thrown
1416 catch (System::InvalidCastException^ )
1418 //ToDo check
1419 throw BridgeRuntimeError("[map_to_uno():" + OUString::unacquired( &type->pTypeName ) + "] could not convert type!");
1421 catch (System::NullReferenceException ^ e)
1423 throw BridgeRuntimeError("[map_to_uno()] Illegal null reference passed!\n" + mapCliString(e->StackTrace));
1425 catch (BridgeRuntimeError& )
1427 throw;
1429 catch (...)
1431 OSL_ASSERT(0);
1432 throw;
1437 @param info
1438 The expected target type. Currently info is provided when this method is called
1439 to convert the in/out and out parameters of a call from cli to uno. Then info
1440 is always a byref type, e.g. "System.String&". info is used for Any and Enum conversion.
1441 @param bDontCreateObj
1442 false - a new object is created which holds the mapped uno value and is assigned to
1443 cli_data.
1444 true - cli_data already contains the newly constructed object. This is the case if
1445 a struct is converted then on the first call to map_to_cli the new object is created.
1446 If the struct inherits another struct then this function is called recursively while the
1447 newly created object is passed in cli_data.
1449 void Bridge::map_to_cli(
1450 System::Object^ *cli_data, void const * uno_data,
1451 typelib_TypeDescriptionReference * type, System::Type^ info,
1452 bool bDontCreateObj) const
1454 switch (type->eTypeClass)
1456 case typelib_TypeClass_CHAR:
1457 *cli_data= *(__wchar_t const*)uno_data;
1458 break;
1459 case typelib_TypeClass_BOOLEAN:
1460 *cli_data = (*(bool const*)uno_data) == sal_True;
1461 break;
1462 case typelib_TypeClass_BYTE:
1463 *cli_data = *(unsigned char const*) uno_data;
1464 break;
1465 case typelib_TypeClass_SHORT:
1466 *cli_data= *(short const*) uno_data;
1467 break;
1468 case typelib_TypeClass_UNSIGNED_SHORT:
1469 *cli_data= *(unsigned short const*) uno_data;
1470 break;
1471 case typelib_TypeClass_LONG:
1472 *cli_data= *(int const*) uno_data;
1473 break;
1474 case typelib_TypeClass_UNSIGNED_LONG:
1475 *cli_data= *(unsigned int const*) uno_data;
1476 break;
1477 case typelib_TypeClass_HYPER:
1478 *cli_data= *(__int64 const*) uno_data;
1479 break;
1480 case typelib_TypeClass_UNSIGNED_HYPER:
1481 *cli_data= *(unsigned __int64 const*) uno_data;
1482 break;
1483 case typelib_TypeClass_FLOAT:
1484 *cli_data= *(float const*) uno_data;
1485 break;
1486 case typelib_TypeClass_DOUBLE:
1487 *cli_data= *(double const*) uno_data;
1488 break;
1489 case typelib_TypeClass_STRING:
1491 rtl_uString const* sVal= NULL;
1492 sVal= *(rtl_uString* const*) uno_data;
1493 *cli_data= gcnew System::String((__wchar_t*) sVal->buffer,0, sVal->length);
1494 break;
1496 case typelib_TypeClass_TYPE:
1498 *cli_data= mapUnoType( *(typelib_TypeDescriptionReference * const *)uno_data );
1499 break;
1501 case typelib_TypeClass_ANY:
1503 uno_Any const * pAny = (uno_Any const *)uno_data;
1504 if (typelib_TypeClass_VOID != pAny->pType->eTypeClass)
1506 System::Object^ objCli= nullptr;
1507 map_to_cli(
1508 &objCli, pAny->pData, pAny->pType, nullptr,
1509 false);
1511 uno::Any anyVal(mapUnoType(pAny->pType), objCli);
1512 *cli_data= anyVal;
1514 else
1515 { // void any
1516 *cli_data= uno::Any::VOID;
1518 break;
1520 case typelib_TypeClass_ENUM:
1522 if (info != nullptr)
1524 OSL_ASSERT(info->IsByRef);
1525 info= info->GetElementType();
1526 *cli_data= System::Enum::ToObject(info, *(System::Int32*) uno_data);
1528 else
1529 *cli_data= System::Enum::ToObject(
1530 mapUnoType(type), *(System::Int32*) uno_data);
1531 break;
1533 case typelib_TypeClass_STRUCT:
1534 case typelib_TypeClass_EXCEPTION:
1536 TypeDescr td( type );
1537 typelib_CompoundTypeDescription * comp_td =
1538 (typelib_CompoundTypeDescription *) td.get();
1539 if ( ! ((typelib_TypeDescription*) comp_td)->bComplete)
1540 ::typelib_typedescription_complete(
1541 (typelib_TypeDescription**) & comp_td );
1544 //create the type
1545 System::Type^ cliType= loadCliType(td.get()->pTypeName);
1546 //detect if we recursively convert inherited structures
1547 //If this point is reached because of a recursive call during covering a
1548 //struct then we must not create a new object rather we use the one in
1549 // cli_data argument.
1550 System::Object^ cliObj;
1551 if (bDontCreateObj)
1552 cliObj = *cli_data; // recursive call
1553 else
1555 //Special handling for Exception conversion. We must call constructor System::Exception
1556 //to pass the message string
1557 if (ucss::uno::Exception::typeid->IsAssignableFrom(cliType))
1559 //We need to get the Message field. Therefore we must obtain the offset from
1560 //the typedescription. The base interface of all exceptions is
1561 //com::sun::star::uno::Exception which contains the message
1562 typelib_CompoundTypeDescription* pCTD = comp_td;
1563 while (pCTD->pBaseTypeDescription)
1564 pCTD = pCTD->pBaseTypeDescription;
1565 int nPos = -1;
1567 OUString usMessageMember("Message");
1568 for (int i = 0; i < pCTD->nMembers; i ++)
1570 if (usMessageMember.equals(pCTD->ppMemberNames[i]))
1572 nPos = i;
1573 break;
1576 OSL_ASSERT (nPos != -1);
1577 int offset = pCTD->pMemberOffsets[nPos];
1578 //With the offset within the exception we can get the message string
1579 System::String^ sMessage = mapUnoString(*(rtl_uString**)
1580 ((char*) uno_data + offset));
1581 //We need to find a constructor for the exception that takes the message string
1582 //We assume that the first argument is the message string
1583 cli::array<sr::ConstructorInfo^>^ arCtorInfo = cliType->GetConstructors();
1584 sr::ConstructorInfo^ ctorInfo = nullptr;
1585 int numCtors = arCtorInfo->Length;
1586 //Constructor must at least have 2 params for the base
1587 //unoidl.com.sun.star.uno.Exception (String, Object);
1588 cli::array<sr::ParameterInfo^>^ arParamInfo;
1589 for (int i = 0; i < numCtors; i++)
1591 arParamInfo = arCtorInfo[i]->GetParameters();
1592 if (arParamInfo->Length < 2)
1593 continue;
1594 ctorInfo = arCtorInfo[i];
1595 break;
1597 OSL_ASSERT(arParamInfo[0]->ParameterType->Equals(System::String::typeid)
1598 && arParamInfo[1]->ParameterType->Equals(System::Object::typeid)
1599 && arParamInfo[0]->Position == 0
1600 && arParamInfo[1]->Position == 1);
1601 //Prepare parameters for constructor
1602 int numArgs = arParamInfo->Length;
1603 cli::array<System::Object^>^ args = gcnew cli::array<System::Object^>(numArgs);
1604 //only initialize the first argument with the message
1605 args[0] = sMessage;
1606 cliObj = ctorInfo->Invoke(args);
1608 else
1609 cliObj = System::Activator::CreateInstance(cliType);
1611 sal_Int32 * pMemberOffsets = comp_td->pMemberOffsets;
1613 if (comp_td->pBaseTypeDescription)
1615 //convert inherited struct
1616 //cliObj is passed inout (args in_param, out_param are true), hence the passed
1617 // cliObj is used by the callee instead of a newly created struct
1618 map_to_cli(
1619 &cliObj, uno_data,
1620 ((typelib_TypeDescription *)comp_td->pBaseTypeDescription)->pWeakRef, nullptr,
1621 true);
1623 OUString usUnoException("com.sun.star.uno.Exception");
1624 for (sal_Int32 nPos = comp_td->nMembers; nPos--; )
1626 typelib_TypeDescriptionReference * member_type = comp_td->ppTypeRefs[ nPos ];
1627 System::String^ sMemberName= mapUnoString(comp_td->ppMemberNames[nPos]);
1628 sr::FieldInfo^ aField= cliType->GetField(sMemberName);
1629 // special case for Exception.Message. The field has already been
1630 // set while constructing cli object
1631 if ( ! aField && usUnoException.equals(td.get()->pTypeName))
1633 continue;
1635 void const * p = (char const *)uno_data + pMemberOffsets[ nPos ];
1636 switch (member_type->eTypeClass)
1638 case typelib_TypeClass_CHAR:
1639 aField->SetValue(cliObj, *(System::Char*) p);
1640 break;
1641 case typelib_TypeClass_BOOLEAN:
1642 aField->SetValue(cliObj, *(System::Boolean*) p);
1643 break;
1644 case typelib_TypeClass_BYTE:
1645 aField->SetValue(cliObj, *(System::Byte*) p);
1646 break;
1647 case typelib_TypeClass_SHORT:
1648 aField->SetValue(cliObj, *(System::Int16*) p);
1649 break;
1650 case typelib_TypeClass_UNSIGNED_SHORT:
1651 aField->SetValue(cliObj, *(System::UInt16*) p);
1652 break;
1653 case typelib_TypeClass_LONG:
1654 aField->SetValue(cliObj, *(System::Int32*) p);
1655 break;
1656 case typelib_TypeClass_UNSIGNED_LONG:
1657 aField->SetValue(cliObj, *(System::UInt32*) p);
1658 break;
1659 case typelib_TypeClass_HYPER:
1660 aField->SetValue(cliObj, *(System::Int64*) p);
1661 break;
1662 case typelib_TypeClass_UNSIGNED_HYPER:
1663 aField->SetValue(cliObj, *(System::UInt64*) p);
1664 break;
1665 case typelib_TypeClass_FLOAT:
1666 aField->SetValue(cliObj, *(System::Single*) p);
1667 break;
1668 case typelib_TypeClass_DOUBLE:
1669 aField->SetValue(cliObj, *(System::Double*) p);
1670 break;
1671 default:
1673 System::Object^ cli_val;
1674 map_to_cli(
1675 &cli_val, p, member_type, nullptr,
1676 false);
1677 aField->SetValue(cliObj, cli_val);
1678 break;
1682 *cli_data= cliObj;
1683 break;
1685 case typelib_TypeClass_SEQUENCE:
1687 sal_Int32 nElements;
1688 uno_Sequence const * seq = 0;
1689 seq = *(uno_Sequence * const *)uno_data;
1690 nElements = seq->nElements;
1692 TypeDescr td( type );
1693 typelib_TypeDescriptionReference * element_type =
1694 ((typelib_IndirectTypeDescription *)td.get())->pType;
1696 switch (element_type->eTypeClass)
1698 case typelib_TypeClass_CHAR:
1700 cli::array<System::Char>^ arChar= gcnew cli::array<System::Char>(nElements);
1701 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arChar, 0, nElements);
1702 *cli_data= arChar;
1703 break;
1705 case typelib_TypeClass_BOOLEAN:
1707 cli::array<System::Byte>^ arBool= gcnew cli::array<System::Byte>(nElements);
1708 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arBool, 0, nElements);
1709 *cli_data= dynamic_cast<cli::array<System::Boolean>^>(arBool);
1710 break;
1712 case typelib_TypeClass_BYTE:
1714 cli::array<System::Byte>^ arByte= gcnew cli::array<System::Byte>(nElements);
1715 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arByte, 0, nElements);
1716 *cli_data= arByte;
1717 break;
1719 case typelib_TypeClass_SHORT:
1721 cli::array<System::Int16>^ arShort= gcnew cli::array<System::Int16>(nElements);
1722 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arShort, 0, nElements);
1723 *cli_data= arShort;
1724 break;
1726 case typelib_TypeClass_UNSIGNED_SHORT:
1728 cli::array<System::UInt16>^ arUInt16= gcnew cli::array<System::UInt16>(nElements);
1729 sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int16>^>(arUInt16),
1730 0, nElements);
1731 *cli_data= arUInt16;
1732 break;
1734 case typelib_TypeClass_LONG:
1736 cli::array<System::Int32>^ arInt32= gcnew cli::array<System::Int32>(nElements);
1737 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt32, 0, nElements);
1738 *cli_data= arInt32;
1739 break;
1741 case typelib_TypeClass_UNSIGNED_LONG:
1743 cli::array<System::UInt32>^ arUInt32= gcnew cli::array<System::UInt32>(nElements);
1744 sri::Marshal::Copy( IntPtr((void*) &seq->elements), dynamic_cast<cli::array<System::Int32>^>(arUInt32),
1745 0, nElements);
1746 *cli_data= arUInt32;
1747 break;
1749 case typelib_TypeClass_HYPER:
1751 cli::array<System::Int64>^ arInt64= gcnew cli::array<System::Int64>(nElements);
1752 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arInt64, 0, nElements);
1753 *cli_data= arInt64;
1754 break;
1756 //FIXME: Marshal::Copy of UInt64?
1757 case typelib_TypeClass_UNSIGNED_HYPER:
1759 cli::array<System::IntPtr>^ arUInt64= gcnew cli::array<System::IntPtr>(nElements);
1760 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arUInt64, 0, nElements);
1761 *cli_data= dynamic_cast<cli::array<System::UInt64>^>(arUInt64);
1762 break;
1764 case typelib_TypeClass_FLOAT:
1766 cli::array<System::Single>^ arSingle= gcnew cli::array<System::Single>(nElements);
1767 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arSingle, 0, nElements);
1768 *cli_data= arSingle;
1769 break;
1771 case typelib_TypeClass_DOUBLE:
1773 cli::array<System::Double>^ arDouble= gcnew cli::array<System::Double>(nElements);
1774 sri::Marshal::Copy( IntPtr((void*) &seq->elements), arDouble, 0, nElements);
1775 *cli_data= arDouble;
1776 break;
1778 case typelib_TypeClass_STRING:
1780 cli::array<System::String^>^ arString= gcnew cli::array<System::String^>(nElements);
1781 for (int i= 0; i < nElements; i++)
1783 rtl_uString *aStr= ((rtl_uString**)(&seq->elements))[i];
1784 arString[i]= gcnew System::String( (__wchar_t *) &aStr->buffer, 0, aStr->length);
1786 *cli_data= arString;
1787 break;
1789 case typelib_TypeClass_TYPE:
1791 cli::array<System::Type^>^ arType= gcnew cli::array<System::Type^>(nElements);
1792 for (int i= 0; i < nElements; i++)
1794 arType[i]=
1795 mapUnoType( ((typelib_TypeDescriptionReference**) seq->elements)[i]);
1797 *cli_data= arType;
1798 break;
1800 case typelib_TypeClass_ANY:
1802 cli::array<uno::Any>^ arCli= gcnew cli::array<uno::Any>(nElements);
1803 uno_Any const * p = (uno_Any const *)seq->elements;
1804 for (sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1806 System::Object^ cli_obj = nullptr;
1807 map_to_cli(
1808 &cli_obj, &p[ nPos ], element_type, nullptr, false);
1809 arCli[nPos]= *safe_cast<uno::Any^>(cli_obj);
1811 *cli_data= arCli;
1812 break;
1814 case typelib_TypeClass_ENUM:
1816 //get the Enum type
1817 System::Type^ enumType= nullptr;
1818 if (info != nullptr)
1820 //info is EnumType[]&, remove &
1821 OSL_ASSERT(info->IsByRef);
1822 enumType = info->GetElementType();
1823 //enumType is EnumType[], remove []
1824 enumType = enumType->GetElementType();
1826 else
1827 enumType= mapUnoType(element_type);
1829 System::Array^ arEnum = System::Array::CreateInstance(
1830 enumType, nElements);
1831 for (int i= 0; i < nElements; i++)
1833 arEnum->SetValue(System::Enum::ToObject(enumType,
1834 ((sal_Int32*) seq->elements)[i]), i);
1836 *cli_data = arEnum;
1837 break;
1839 case typelib_TypeClass_STRUCT:
1840 case typelib_TypeClass_EXCEPTION:
1842 TypeDescr element_td( element_type );
1843 System::Array^ ar= System::Array::CreateInstance(
1844 mapUnoType(element_type),nElements);
1845 if (0 < nElements)
1847 // ToDo check this
1848 char * p = (char *) &seq->elements;
1849 sal_Int32 nSize = element_td.get()->nSize;
1850 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1852 System::Object^ val;
1853 map_to_cli(
1854 &val, p + (nSize * nPos), element_type, nullptr, false);
1855 ar->SetValue(val, nPos);
1858 *cli_data = ar;
1859 break;
1861 // ToDo, verify
1862 case typelib_TypeClass_SEQUENCE:
1864 System::Array ^ar= System::Array::CreateInstance(
1865 mapUnoType(element_type), nElements);
1866 if (0 < nElements)
1868 TypeDescr element_td( element_type );
1869 uno_Sequence ** elements = (uno_Sequence**) seq->elements;
1870 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1872 System::Object^ val;
1873 map_to_cli(
1874 &val, &elements[nPos], element_type, nullptr, false);
1875 ar->SetValue(val, nPos);
1878 *cli_data = ar;
1879 break;
1881 case typelib_TypeClass_INTERFACE:
1883 TypeDescr element_td( element_type );
1884 System::Type ^ ifaceType= mapUnoType(element_type);
1885 System::Array^ ar= System::Array::CreateInstance(ifaceType, nElements);
1887 char * p = (char *)seq->elements;
1888 sal_Int32 nSize = element_td.get()->nSize;
1889 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
1891 System::Object^ val;
1892 map_to_cli(
1893 &val, p + (nSize * nPos), element_type, nullptr, false);
1895 ar->SetValue(val, nPos);
1897 *cli_data= ar;
1898 break;
1900 default:
1902 throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) +
1903 "] unsupported element type: " + OUString::unacquired( &element_type->pTypeName ));
1906 break;
1908 case typelib_TypeClass_INTERFACE:
1910 uno_Interface * pUnoI = *(uno_Interface * const *)uno_data;
1911 if (0 != pUnoI)
1913 TypeDescr td( type );
1914 *cli_data= map_uno2cli( pUnoI, reinterpret_cast<
1915 typelib_InterfaceTypeDescription*>(td.get())) ;
1917 else
1918 *cli_data= nullptr;
1919 break;
1921 default:
1923 //ToDo check this exception. The String is probably crippled
1924 throw BridgeRuntimeError("[map_to_cli():" + OUString::unacquired( &type->pTypeName ) + "] unsupported type!");
1926 } //switch
1927 } // method
1928 } // namespace
1930 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */