tdf#144694 In direct SQL dialog, activate options 'Run SQL command
[LibreOffice.git] / cli_ure / source / uno_bridge / cli_data.cxx
blobc6db58c2bb3db6a35b17689b72027191715fb595
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 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 assert(arParamInfo);
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 System::Int32(((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, System::Int32(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, System::Int32(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, System::Int32(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: */