1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26
27 #include <osl/diagnose.h>
28 #include <cppuhelper/factory.hxx>
29 #include <cppuhelper/implementationentry.hxx>
30 #include <cppuhelper/implbase2.hxx>
31
32 #include <typelib/typedescription.hxx>
33 #include <uno/data.h>
34
35 #ifdef WNT
36 #include <cmath>
37 #else
38 #include <math.h>
39 #endif
40 #include <float.h>
41
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #include <com/sun/star/script/XTypeConverter.hpp>
45 #include <com/sun/star/script/FailReason.hpp>
46 #include <com/sun/star/container/XSet.hpp>
47 #include <com/sun/star/registry/XRegistryKey.hpp>
48
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::script;
52 using namespace com::sun::star::registry;
53 using namespace cppu;
54 using namespace rtl;
55 using namespace osl;
56
57 #define SERVICENAME "com.sun.star.script.Converter"
58 #define IMPLNAME "com.sun.star.comp.stoc.TypeConverter"
59
60
61 extern rtl_StandardModuleCount g_moduleCount;
62
63 namespace stoc_services
64 {
tcv_getSupportedServiceNames()65 Sequence< OUString > tcv_getSupportedServiceNames()
66 {
67 static Sequence < OUString > *pNames = 0;
68 if( ! pNames )
69 {
70 MutexGuard guard( Mutex::getGlobalMutex() );
71 if( !pNames )
72 {
73 static Sequence< OUString > seqNames(1);
74 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
75 pNames = &seqNames;
76 }
77 }
78 return *pNames;
79 }
80
tcv_getImplementationName()81 OUString tcv_getImplementationName()
82 {
83 static OUString *pImplName = 0;
84 if( ! pImplName )
85 {
86 MutexGuard guard( Mutex::getGlobalMutex() );
87 if( ! pImplName )
88 {
89 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
90 pImplName = &implName;
91 }
92 }
93 return *pImplName;
94 }
95 }
96
97 namespace stoc_tcv
98 {
99
100 static const sal_uInt64 SAL_UINT64_MAX =
101 ((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
102 static const sal_Int64 SAL_INT64_MAX =
103 (sal_Int64)((((sal_uInt64)0x7fffffff) << 32) | (sal_uInt64)0xffffffff);
104 static const sal_Int64 SAL_INT64_MIN =
105 (sal_Int64)(((sal_uInt64)0x80000000) << 32);
106
107 /* MS Visual C++ no conversion from unsigned __int64 to double */
108 #ifdef _MSC_VER
109 static const double DOUBLE_SAL_UINT64_MAX = ((((double)SAL_INT64_MAX) * 2) + 1);
110
unsigned_int64_to_double(sal_uInt64 n)111 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () )
112 {
113 sal_uInt64 n2 = (n / 3);
114 n -= (2 * n2);
115 return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n);
116 }
117 #else
118 static const double DOUBLE_SAL_UINT64_MAX =
119 (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
120
unsigned_int64_to_double(sal_uInt64 n)121 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () )
122 {
123 return (double)n;
124 }
125 #endif
126
127
128 //--------------------------------------------------------------------------------------------------
round(double aVal)129 static inline double round( double aVal )
130 {
131 sal_Bool bPos = (aVal >= 0.0); //
132 aVal = ::fabs( aVal );
133 double aUpper = ::ceil( aVal );
134
135 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
136 return (bPos ? aVal : -aVal);
137 }
138
139 //--------------------------------------------------------------------------------------------------
getNumericValue(double & rfVal,const OUString & rStr)140 static sal_Bool getNumericValue( double & rfVal, const OUString & rStr )
141 {
142 double fRet = rStr.toDouble();
143 if (fRet == 0.0)
144 {
145 sal_Int32 nLen = rStr.getLength();
146 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
147 {
148 rfVal = 0.0;
149 return sal_True;
150 }
151
152 OUString trim( rStr.trim() );
153
154 // try hex
155 sal_Int32 nX = trim.indexOf( 'x' );
156 if (nX < 0)
157 nX = trim.indexOf( 'X' );
158
159 if (nX > 0 && trim[nX-1] == '0') // 0x
160 {
161 sal_Bool bNeg = sal_False;
162 switch (nX)
163 {
164 case 2: // (+|-)0x...
165 if (trim[0] == '-')
166 bNeg = sal_True;
167 else if (trim[0] != '+')
168 return sal_False;
169 case 1: // 0x...
170 break;
171 default:
172 return sal_False;
173 }
174
175 OUString aHexRest( trim.copy( nX+1 ) );
176 sal_Int64 nRet = aHexRest.toInt64( 16 );
177
178 if (nRet == 0)
179 {
180 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
181 {
182 if (aHexRest[nPos] != '0')
183 return sal_False;
184 }
185 }
186
187 rfVal = (bNeg ? -(double)nRet : (double)nRet);
188 return sal_True;
189 }
190
191 nLen = trim.getLength();
192 sal_Int32 nPos = 0;
193
194 // skip +/-
195 if (nLen && (trim[0] == '-' || trim[0] == '+'))
196 ++nPos;
197
198 while (nPos < nLen) // skip leading zeros
199 {
200 if (trim[nPos] != '0')
201 {
202 if (trim[nPos] != '.')
203 return sal_False;
204 ++nPos;
205 while (nPos < nLen) // skip trailing zeros
206 {
207 if (trim[nPos] != '0')
208 return sal_False;
209 ++nPos;
210 }
211 break;
212 }
213 ++nPos;
214 }
215 }
216 rfVal = fRet;
217 return sal_True;
218 }
219
220 //==================================================================================================
getHyperValue(sal_Int64 & rnVal,const OUString & rStr)221 static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
222 {
223 sal_Int32 nLen = rStr.getLength();
224 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
225 {
226 rnVal = 0;
227 return sal_True;
228 }
229
230 OUString trim( rStr.trim() );
231
232 // try hex
233 sal_Int32 nX = trim.indexOf( 'x' );
234 if (nX < 0)
235 nX = trim.indexOf( 'X' );
236
237 if (nX >= 0)
238 {
239 if (nX > 0 && trim[nX-1] == '0') // 0x
240 {
241 sal_Bool bNeg = sal_False;
242 switch (nX)
243 {
244 case 2: // (+|-)0x...
245 if (trim[0] == '-')
246 bNeg = sal_True;
247 else if (trim[0] != '+')
248 return sal_False;
249 case 1: // 0x...
250 break;
251 default:
252 return sal_False;
253 }
254
255 OUString aHexRest( trim.copy( nX+1 ) );
256 sal_Int64 nRet = aHexRest.toInt64( 16 );
257
258 if (nRet == 0)
259 {
260 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
261 {
262 if (aHexRest[nPos] != '0')
263 return sal_False;
264 }
265 }
266
267 rnVal = (bNeg ? -nRet : nRet);
268 return sal_True;
269 }
270 return sal_False;
271 }
272
273 double fVal;
274 if (getNumericValue( fVal, rStr ) &&
275 fVal >= (double)SAL_INT64_MIN &&
276 fVal <= DOUBLE_SAL_UINT64_MAX)
277 {
278 rnVal = (sal_Int64)round( fVal );
279 return sal_True;
280 }
281 return sal_False;
282 }
283
284 //==================================================================================================
285 class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo >
286 {
287 // ...misc helpers...
288 sal_Int64 toHyper(
289 const Any& rAny, sal_Int64 min = SAL_INT64_MIN, sal_uInt64 max = SAL_UINT64_MAX );
290 double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const;
291
292 public:
293 TypeConverter_Impl();
294 virtual ~TypeConverter_Impl();
295
296 // XServiceInfo
297 virtual OUString SAL_CALL getImplementationName();
298 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName);
299 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void);
300
301 // XTypeConverter
302 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType );
303 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType );
304 };
305
TypeConverter_Impl()306 TypeConverter_Impl::TypeConverter_Impl()
307 {
308 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
309 }
310
~TypeConverter_Impl()311 TypeConverter_Impl::~TypeConverter_Impl()
312 {
313 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
314 }
315
316 // XServiceInfo
getImplementationName()317 OUString TypeConverter_Impl::getImplementationName()
318 {
319 return stoc_services::tcv_getImplementationName();
320 }
321
322 // XServiceInfo
supportsService(const OUString & ServiceName)323 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName)
324 {
325 Sequence< OUString > aSNL = getSupportedServiceNames();
326 const OUString * pArray = aSNL.getConstArray();
327 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
328 if( pArray[i] == ServiceName )
329 return sal_True;
330 return sal_False;
331 }
332
333 // XServiceInfo
getSupportedServiceNames(void)334 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void)
335 {
336 return stoc_services::tcv_getSupportedServiceNames();
337 }
338
339 //--------------------------------------------------------------------------------------------------
toHyper(const Any & rAny,sal_Int64 min,sal_uInt64 max)340 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
341 {
342 sal_Int64 nRet;
343 TypeClass aDestinationClass = rAny.getValueTypeClass();
344
345 switch (aDestinationClass)
346 {
347 // ENUM
348 case TypeClass_ENUM:
349 nRet = *(sal_Int32 *)rAny.getValue();
350 break;
351 // BOOL
352 case TypeClass_BOOLEAN:
353 nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0);
354 break;
355 // CHAR, BYTE
356 case TypeClass_CHAR:
357 nRet = *(sal_Unicode *)rAny.getValue();
358 break;
359 case TypeClass_BYTE:
360 nRet = *(sal_Int8 *)rAny.getValue();
361 break;
362 // SHORT
363 case TypeClass_SHORT:
364 nRet = *(sal_Int16 *)rAny.getValue();
365 break;
366 // UNSIGNED SHORT
367 case TypeClass_UNSIGNED_SHORT:
368 nRet = *(sal_uInt16 *)rAny.getValue();
369 break;
370 // LONG
371 case TypeClass_LONG:
372 nRet = *(sal_Int32 *)rAny.getValue();
373 break;
374 // UNSIGNED LONG
375 case TypeClass_UNSIGNED_LONG:
376 nRet = *(sal_uInt32 *)rAny.getValue();
377 break;
378 // HYPER
379 case TypeClass_HYPER:
380 nRet = *(sal_Int64 *)rAny.getValue();
381 break;
382 // UNSIGNED HYPER
383 case TypeClass_UNSIGNED_HYPER:
384 {
385 nRet = *(sal_Int64 *)rAny.getValue();
386 if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound
387 (sal_uInt64)nRet <= max) // upper bound
388 {
389 return nRet;
390 }
391 throw CannotConvertException(
392 OUString( RTL_CONSTASCII_USTRINGPARAM("UNSIGNED HYPER out of range!") ),
393 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
394 }
395
396 // FLOAT, DOUBLE
397 case TypeClass_FLOAT:
398 {
399 double fVal = round( *(float *)rAny.getValue() );
400 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
401 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
402 {
403 return nRet;
404 }
405 throw CannotConvertException(
406 OUString( RTL_CONSTASCII_USTRINGPARAM("FLOAT out of range!") ),
407 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
408 }
409 case TypeClass_DOUBLE:
410 {
411 double fVal = round( *(double *)rAny.getValue() );
412 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
413 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
414 {
415 return nRet;
416 }
417 throw CannotConvertException(
418 OUString( RTL_CONSTASCII_USTRINGPARAM("DOUBLE out of range!") ),
419 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
420 }
421
422 // STRING
423 case TypeClass_STRING:
424 {
425 sal_Int64 fVal = SAL_CONST_INT64(0);
426 if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() ))
427 {
428 throw CannotConvertException(
429 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
430 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
431 }
432 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
433 if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max))
434 return nRet;
435 throw CannotConvertException(
436 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING value out of range!") ),
437 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
438 }
439
440 default:
441 throw CannotConvertException(
442 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
443 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
444 }
445
446 if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max))
447 return nRet;
448 throw CannotConvertException(
449 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
450 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
451 }
452
453 //--------------------------------------------------------------------------------------------------
toDouble(const Any & rAny,double min,double max) const454 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
455 {
456 double fRet;
457 TypeClass aDestinationClass = rAny.getValueTypeClass();
458
459 switch (aDestinationClass)
460 {
461 // ENUM
462 case TypeClass_ENUM:
463 fRet = *(sal_Int32 *)rAny.getValue();
464 break;
465 // BOOL
466 case TypeClass_BOOLEAN:
467 fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0);
468 break;
469 // CHAR, BYTE
470 case TypeClass_CHAR:
471 fRet = *(sal_Unicode *)rAny.getValue();
472 break;
473 case TypeClass_BYTE:
474 fRet = *(sal_Int8 *)rAny.getValue();
475 break;
476 // SHORT
477 case TypeClass_SHORT:
478 fRet = *(sal_Int16 *)rAny.getValue();
479 break;
480 // UNSIGNED SHORT
481 case TypeClass_UNSIGNED_SHORT:
482 fRet = *(sal_uInt16 *)rAny.getValue();
483 break;
484 // LONG
485 case TypeClass_LONG:
486 fRet = *(sal_Int32 *)rAny.getValue();
487 break;
488 // UNSIGNED LONG
489 case TypeClass_UNSIGNED_LONG:
490 fRet = *(sal_uInt32 *)rAny.getValue();
491 break;
492 // HYPER
493 case TypeClass_HYPER:
494 fRet = (double)*(sal_Int64 *)rAny.getValue();
495 break;
496 // UNSIGNED HYPER
497 case TypeClass_UNSIGNED_HYPER:
498 fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() );
499 break;
500 // FLOAT, DOUBLE
501 case TypeClass_FLOAT:
502 fRet = *(float *)rAny.getValue();
503 break;
504 case TypeClass_DOUBLE:
505 fRet = *(double *)rAny.getValue();
506 break;
507
508 // STRING
509 case TypeClass_STRING:
510 {
511 if (! getNumericValue( fRet, *(OUString *)rAny.getValue() ))
512 {
513 throw CannotConvertException(
514 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
515 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
516 }
517 break;
518 }
519
520 default:
521 throw CannotConvertException(
522 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
523 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
524 }
525
526 if (fRet >= min && fRet <= max)
527 return fRet;
528 throw CannotConvertException(
529 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
530 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
531 }
532
533 //--------------------------------------------------------------------------------------------------
convertTo(const Any & rVal,const Type & aDestType)534 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
535 {
536 Type aSourceType = rVal.getValueType();
537 if (aSourceType == aDestType)
538 return rVal;
539
540 TypeClass aSourceClass = aSourceType.getTypeClass();
541 TypeClass aDestinationClass = aDestType.getTypeClass();
542
543 Any aRet;
544
545 // convert to...
546 switch (aDestinationClass)
547 {
548 // --- to VOID ------------------------------------------------------------------------------
549 case TypeClass_VOID:
550 return Any();
551 // --- to ANY -------------------------------------------------------------------------------
552 case TypeClass_ANY:
553 return rVal;
554
555 // --- to STRUCT, UNION, EXCEPTION ----------------------------------------------------------
556 case TypeClass_STRUCT:
557 // case TypeClass_UNION: // xxx todo
558 case TypeClass_EXCEPTION:
559 {
560 // same types or destination type is derived source type?
561 TypeDescription aSourceTD( aSourceType );
562 TypeDescription aDestTD( aDestType );
563 if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
564 {
565 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
566 }
567 else
568 {
569 throw CannotConvertException(
570 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not of same or derived type!") ),
571 Reference< XInterface >(), aDestinationClass,
572 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
573 }
574 break;
575 }
576 // --- to INTERFACE -------------------------------------------------------------------------
577 case TypeClass_INTERFACE:
578 {
579 if (! rVal.hasValue())
580 {
581 // void -> interface (null)
582 void * null_ref = 0;
583 aRet.setValue( &null_ref, aDestType );
584 break;
585 }
586
587 if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
588 !*(XInterface * const *)rVal.getValue())
589 {
590 throw CannotConvertException(
591 OUString( RTL_CONSTASCII_USTRINGPARAM("value is no interface!") ),
592 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
593 }
594 if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
595 aDestType )).hasValue())
596 {
597 throw CannotConvertException(
598 OUString( RTL_CONSTASCII_USTRINGPARAM("value has no such interface!") ),
599 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
600 }
601 break;
602 }
603 // --- to SEQUENCE --------------------------------------------------------------------------
604 case TypeClass_SEQUENCE:
605 {
606 if (aSourceClass==TypeClass_SEQUENCE)
607 {
608 if( aSourceType == aDestType )
609 return rVal;
610
611 TypeDescription aSourceTD( aSourceType );
612 TypeDescription aDestTD( aDestType );
613 typelib_TypeDescription * pSourceElementTD = 0;
614 TYPELIB_DANGER_GET(
615 &pSourceElementTD,
616 ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
617 typelib_TypeDescription * pDestElementTD = 0;
618 TYPELIB_DANGER_GET(
619 &pDestElementTD,
620 ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
621
622 sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
623 uno_Sequence * pRet = 0;
624 uno_sequence_construct(
625 &pRet, aDestTD.get(), 0, nPos,
626 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
627 aRet.setValue( &pRet, aDestTD.get() );
628 uno_destructData(
629 &pRet, aDestTD.get(),
630 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
631 // decr ref count
632
633 char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
634 const char * pSourceElements =
635 (*(const uno_Sequence * const *)rVal.getValue())->elements;
636
637 while (nPos--)
638 {
639 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
640 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
641
642 Any aElement(
643 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
644
645 if (!uno_assignData(
646 pDestPos, pDestElementTD,
647 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
648 ? &aElement
649 : const_cast< void * >( aElement.getValue() )),
650 pDestElementTD,
651 reinterpret_cast< uno_QueryInterfaceFunc >(
652 cpp_queryInterface),
653 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
654 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
655 {
656 OSL_ASSERT( false );
657 }
658 }
659 TYPELIB_DANGER_RELEASE( pDestElementTD );
660 TYPELIB_DANGER_RELEASE( pSourceElementTD );
661 }
662 break;
663 }
664 // --- to ENUM ------------------------------------------------------------------------------
665 case TypeClass_ENUM:
666 {
667 TypeDescription aEnumTD( aDestType );
668 aEnumTD.makeComplete();
669 sal_Int32 nPos = -1;
670
671 if (aSourceClass==TypeClass_STRING)
672 {
673 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
674 {
675 if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase(
676 ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] ))
677 break;
678 }
679 }
680 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
681 aSourceClass!=TypeClass_BOOLEAN &&
682 aSourceClass!=TypeClass_CHAR)
683 {
684 sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff );
685 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
686 {
687 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
688 break;
689 }
690 }
691
692 if (nPos >= 0)
693 {
694 aRet.setValue(
695 &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos],
696 aEnumTD.get() );
697 }
698 else
699 {
700 throw CannotConvertException(
701 OUString(
702 RTL_CONSTASCII_USTRINGPARAM("value cannot be converted to demanded ENUM!") ),
703 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
704 }
705 break;
706 }
707
708 default:
709 // else simple type conversion possible?
710 try
711 {
712 aRet = convertToSimpleType( rVal, aDestinationClass );
713 }
714 catch (IllegalArgumentException &)
715 {
716 // ...FailReason::INVALID is thrown
717 }
718 }
719
720 if (aRet.hasValue())
721 return aRet;
722
723 throw CannotConvertException(
724 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
725 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
726 }
727
728 //--------------------------------------------------------------------------------------------------
convertToSimpleType(const Any & rVal,TypeClass aDestinationClass)729 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
730 {
731 switch (aDestinationClass)
732 {
733 // only simple Conversion of _simple_ types
734 case TypeClass_INTERFACE:
735 case TypeClass_SERVICE:
736 case TypeClass_STRUCT:
737 case TypeClass_TYPEDEF:
738 case TypeClass_UNION:
739 case TypeClass_EXCEPTION:
740 case TypeClass_ARRAY:
741 case TypeClass_SEQUENCE:
742 case TypeClass_ENUM:
743 case TypeClass_UNKNOWN:
744 case TypeClass_MODULE:
745 throw IllegalArgumentException(
746 OUString( RTL_CONSTASCII_USTRINGPARAM("destination type is not simple!") ),
747 Reference< XInterface >(), (sal_Int16) 1 );
748 default:
749 break;
750 }
751
752 Type aSourceType = rVal.getValueType();
753 TypeClass aSourceClass = aSourceType.getTypeClass();
754 if (aDestinationClass == aSourceClass)
755 return rVal;
756
757 Any aRet;
758
759 // Convert to...
760 switch (aDestinationClass)
761 {
762 // --- to VOID ------------------------------------------------------------------------------
763 case TypeClass_VOID:
764 return Any();
765
766 // --- to ANY -------------------------------------------------------------------------------
767 case TypeClass_ANY:
768 return rVal;
769
770 // --- to BOOL ------------------------------------------------------------------------------
771 case TypeClass_BOOLEAN:
772 switch (aSourceClass)
773 {
774 default:
775 {
776 sal_Bool bTmp = (toDouble( rVal ) != 0.0);
777 aRet.setValue( &bTmp, getBooleanCppuType() );
778 }
779 case TypeClass_ENUM: // exclude enums
780 break;
781
782 case TypeClass_STRING:
783 {
784 const OUString & aStr = *(const OUString *)rVal.getValue();
785 if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("0") ) ||
786 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("false") ) ))
787 {
788 sal_Bool bFalse = sal_False;
789 aRet.setValue( &bFalse, getCppuBooleanType() );
790 }
791 else if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("1") ) ||
792 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("true") ) ))
793 {
794 sal_Bool bTrue = sal_True;
795 aRet.setValue( &bTrue, getCppuBooleanType() );
796 }
797 else
798 {
799 throw CannotConvertException(
800 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING has no boolean value!") ),
801 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
802 }
803 }
804 }
805 break;
806
807 // --- to CHAR, BYTE ------------------------------------------------------------------------
808 case TypeClass_CHAR:
809 {
810 if (aSourceClass==TypeClass_STRING)
811 {
812 if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char
813 aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() );
814 }
815 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
816 aSourceClass!=TypeClass_CHAR)
817 {
818 sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range
819 aRet.setValue( &cRet, ::getCharCppuType() );
820 }
821 break;
822 }
823 case TypeClass_BYTE:
824 aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) );
825 break;
826
827 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
828 case TypeClass_SHORT:
829 aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) );
830 break;
831 case TypeClass_UNSIGNED_SHORT:
832 aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) );
833 break;
834
835 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
836 case TypeClass_LONG:
837 aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) );
838 break;
839 case TypeClass_UNSIGNED_LONG:
840 aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) );
841 break;
842
843 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
844 case TypeClass_HYPER:
845 aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
846 break;
847 case TypeClass_UNSIGNED_HYPER:
848 aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) );
849 break;
850
851 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
852 case TypeClass_FLOAT:
853 aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
854 break;
855 case TypeClass_DOUBLE:
856 aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) );
857 break;
858
859 // --- to STRING ----------------------------------------------------------------------------
860 case TypeClass_STRING:
861 switch (aSourceClass)
862 {
863 case TypeClass_ENUM:
864 {
865 TypeDescription aEnumTD( aSourceType );
866 aEnumTD.makeComplete();
867 sal_Int32 nPos;
868 sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue();
869 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
870 {
871 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
872 break;
873 }
874 if (nPos >= 0)
875 {
876 aRet.setValue(
877 &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos],
878 ::getCppuType( (const OUString *)0 ) );
879 }
880 else
881 {
882 throw CannotConvertException(
883 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not ENUM!") ),
884 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
885 }
886 break;
887 }
888
889 case TypeClass_BOOLEAN:
890 aRet <<= OUString::createFromAscii( (*(sal_Bool *)rVal.getValue() ? "true" : "false") );
891 break;
892 case TypeClass_CHAR:
893 aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 );
894 break;
895
896 case TypeClass_BYTE:
897 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() );
898 break;
899 case TypeClass_SHORT:
900 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() );
901 break;
902 case TypeClass_UNSIGNED_SHORT:
903 aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() );
904 break;
905 case TypeClass_LONG:
906 aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() );
907 break;
908 case TypeClass_UNSIGNED_LONG:
909 aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() );
910 break;
911 case TypeClass_HYPER:
912 aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() );
913 break;
914 // case TypeClass_UNSIGNED_HYPER:
915 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
916 // break;
917 // handle unsigned hyper like double
918
919 default:
920 aRet <<= OUString::valueOf( toDouble( rVal ) );
921 }
922 break;
923
924 default:
925 OSL_ASSERT(false);
926 break;
927 }
928
929 if (aRet.hasValue())
930 return aRet;
931
932 throw CannotConvertException(
933 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
934 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
935 }
936 }
937
938 namespace stoc_services
939 {
940 //*************************************************************************
TypeConverter_Impl_CreateInstance(const Reference<XComponentContext> &)941 Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
942 const Reference< XComponentContext > & )
943 {
944 static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
945 return s_ref;
946 }
947 }
948