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 throw( CannotConvertException );
291 double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const
292 throw( CannotConvertException );
293
294 public:
295 TypeConverter_Impl();
296 virtual ~TypeConverter_Impl();
297
298 // XServiceInfo
299 virtual OUString SAL_CALL getImplementationName() throw( RuntimeException );
300 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName)
301 throw( RuntimeException );
302 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
303 throw( RuntimeException );
304
305 // XTypeConverter
306 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType )
307 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
308 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType )
309 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
310 };
311
TypeConverter_Impl()312 TypeConverter_Impl::TypeConverter_Impl()
313 {
314 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
315 }
316
~TypeConverter_Impl()317 TypeConverter_Impl::~TypeConverter_Impl()
318 {
319 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
320 }
321
322 // XServiceInfo
getImplementationName()323 OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException )
324 {
325 return stoc_services::tcv_getImplementationName();
326 }
327
328 // XServiceInfo
supportsService(const OUString & ServiceName)329 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException )
330 {
331 Sequence< OUString > aSNL = getSupportedServiceNames();
332 const OUString * pArray = aSNL.getConstArray();
333 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
334 if( pArray[i] == ServiceName )
335 return sal_True;
336 return sal_False;
337 }
338
339 // XServiceInfo
getSupportedServiceNames(void)340 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException )
341 {
342 return stoc_services::tcv_getSupportedServiceNames();
343 }
344
345 //--------------------------------------------------------------------------------------------------
toHyper(const Any & rAny,sal_Int64 min,sal_uInt64 max)346 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
347 throw( CannotConvertException )
348 {
349 sal_Int64 nRet;
350 TypeClass aDestinationClass = rAny.getValueTypeClass();
351
352 switch (aDestinationClass)
353 {
354 // ENUM
355 case TypeClass_ENUM:
356 nRet = *(sal_Int32 *)rAny.getValue();
357 break;
358 // BOOL
359 case TypeClass_BOOLEAN:
360 nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0);
361 break;
362 // CHAR, BYTE
363 case TypeClass_CHAR:
364 nRet = *(sal_Unicode *)rAny.getValue();
365 break;
366 case TypeClass_BYTE:
367 nRet = *(sal_Int8 *)rAny.getValue();
368 break;
369 // SHORT
370 case TypeClass_SHORT:
371 nRet = *(sal_Int16 *)rAny.getValue();
372 break;
373 // UNSIGNED SHORT
374 case TypeClass_UNSIGNED_SHORT:
375 nRet = *(sal_uInt16 *)rAny.getValue();
376 break;
377 // LONG
378 case TypeClass_LONG:
379 nRet = *(sal_Int32 *)rAny.getValue();
380 break;
381 // UNSIGNED LONG
382 case TypeClass_UNSIGNED_LONG:
383 nRet = *(sal_uInt32 *)rAny.getValue();
384 break;
385 // HYPER
386 case TypeClass_HYPER:
387 nRet = *(sal_Int64 *)rAny.getValue();
388 break;
389 // UNSIGNED HYPER
390 case TypeClass_UNSIGNED_HYPER:
391 {
392 nRet = *(sal_Int64 *)rAny.getValue();
393 if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound
394 (sal_uInt64)nRet <= max) // upper bound
395 {
396 return nRet;
397 }
398 throw CannotConvertException(
399 OUString( RTL_CONSTASCII_USTRINGPARAM("UNSIGNED HYPER out of range!") ),
400 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
401 }
402
403 // FLOAT, DOUBLE
404 case TypeClass_FLOAT:
405 {
406 double fVal = round( *(float *)rAny.getValue() );
407 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
408 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
409 {
410 return nRet;
411 }
412 throw CannotConvertException(
413 OUString( RTL_CONSTASCII_USTRINGPARAM("FLOAT out of range!") ),
414 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
415 }
416 case TypeClass_DOUBLE:
417 {
418 double fVal = round( *(double *)rAny.getValue() );
419 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
420 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
421 {
422 return nRet;
423 }
424 throw CannotConvertException(
425 OUString( RTL_CONSTASCII_USTRINGPARAM("DOUBLE out of range!") ),
426 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
427 }
428
429 // STRING
430 case TypeClass_STRING:
431 {
432 sal_Int64 fVal = SAL_CONST_INT64(0);
433 if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() ))
434 {
435 throw CannotConvertException(
436 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
437 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
438 }
439 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
440 if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max))
441 return nRet;
442 throw CannotConvertException(
443 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING value out of range!") ),
444 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
445 }
446
447 default:
448 throw CannotConvertException(
449 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
450 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
451 }
452
453 if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max))
454 return nRet;
455 throw CannotConvertException(
456 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
457 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
458 }
459
460 //--------------------------------------------------------------------------------------------------
toDouble(const Any & rAny,double min,double max) const461 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
462 throw( CannotConvertException )
463 {
464 double fRet;
465 TypeClass aDestinationClass = rAny.getValueTypeClass();
466
467 switch (aDestinationClass)
468 {
469 // ENUM
470 case TypeClass_ENUM:
471 fRet = *(sal_Int32 *)rAny.getValue();
472 break;
473 // BOOL
474 case TypeClass_BOOLEAN:
475 fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0);
476 break;
477 // CHAR, BYTE
478 case TypeClass_CHAR:
479 fRet = *(sal_Unicode *)rAny.getValue();
480 break;
481 case TypeClass_BYTE:
482 fRet = *(sal_Int8 *)rAny.getValue();
483 break;
484 // SHORT
485 case TypeClass_SHORT:
486 fRet = *(sal_Int16 *)rAny.getValue();
487 break;
488 // UNSIGNED SHORT
489 case TypeClass_UNSIGNED_SHORT:
490 fRet = *(sal_uInt16 *)rAny.getValue();
491 break;
492 // LONG
493 case TypeClass_LONG:
494 fRet = *(sal_Int32 *)rAny.getValue();
495 break;
496 // UNSIGNED LONG
497 case TypeClass_UNSIGNED_LONG:
498 fRet = *(sal_uInt32 *)rAny.getValue();
499 break;
500 // HYPER
501 case TypeClass_HYPER:
502 fRet = (double)*(sal_Int64 *)rAny.getValue();
503 break;
504 // UNSIGNED HYPER
505 case TypeClass_UNSIGNED_HYPER:
506 fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() );
507 break;
508 // FLOAT, DOUBLE
509 case TypeClass_FLOAT:
510 fRet = *(float *)rAny.getValue();
511 break;
512 case TypeClass_DOUBLE:
513 fRet = *(double *)rAny.getValue();
514 break;
515
516 // STRING
517 case TypeClass_STRING:
518 {
519 if (! getNumericValue( fRet, *(OUString *)rAny.getValue() ))
520 {
521 throw CannotConvertException(
522 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
523 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
524 }
525 break;
526 }
527
528 default:
529 throw CannotConvertException(
530 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
531 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
532 }
533
534 if (fRet >= min && fRet <= max)
535 return fRet;
536 throw CannotConvertException(
537 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
538 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
539 }
540
541 //--------------------------------------------------------------------------------------------------
convertTo(const Any & rVal,const Type & aDestType)542 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
543 throw( IllegalArgumentException, CannotConvertException, RuntimeException)
544 {
545 Type aSourceType = rVal.getValueType();
546 if (aSourceType == aDestType)
547 return rVal;
548
549 TypeClass aSourceClass = aSourceType.getTypeClass();
550 TypeClass aDestinationClass = aDestType.getTypeClass();
551
552 Any aRet;
553
554 // convert to...
555 switch (aDestinationClass)
556 {
557 // --- to VOID ------------------------------------------------------------------------------
558 case TypeClass_VOID:
559 return Any();
560 // --- to ANY -------------------------------------------------------------------------------
561 case TypeClass_ANY:
562 return rVal;
563
564 // --- to STRUCT, UNION, EXCEPTION ----------------------------------------------------------
565 case TypeClass_STRUCT:
566 // case TypeClass_UNION: // xxx todo
567 case TypeClass_EXCEPTION:
568 {
569 // same types or destination type is derived source type?
570 TypeDescription aSourceTD( aSourceType );
571 TypeDescription aDestTD( aDestType );
572 if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
573 {
574 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
575 }
576 else
577 {
578 throw CannotConvertException(
579 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not of same or derived type!") ),
580 Reference< XInterface >(), aDestinationClass,
581 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
582 }
583 break;
584 }
585 // --- to INTERFACE -------------------------------------------------------------------------
586 case TypeClass_INTERFACE:
587 {
588 if (! rVal.hasValue())
589 {
590 // void -> interface (null)
591 void * null_ref = 0;
592 aRet.setValue( &null_ref, aDestType );
593 break;
594 }
595
596 if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
597 !*(XInterface * const *)rVal.getValue())
598 {
599 throw CannotConvertException(
600 OUString( RTL_CONSTASCII_USTRINGPARAM("value is no interface!") ),
601 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
602 }
603 if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
604 aDestType )).hasValue())
605 {
606 throw CannotConvertException(
607 OUString( RTL_CONSTASCII_USTRINGPARAM("value has no such interface!") ),
608 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
609 }
610 break;
611 }
612 // --- to SEQUENCE --------------------------------------------------------------------------
613 case TypeClass_SEQUENCE:
614 {
615 if (aSourceClass==TypeClass_SEQUENCE)
616 {
617 if( aSourceType == aDestType )
618 return rVal;
619
620 TypeDescription aSourceTD( aSourceType );
621 TypeDescription aDestTD( aDestType );
622 typelib_TypeDescription * pSourceElementTD = 0;
623 TYPELIB_DANGER_GET(
624 &pSourceElementTD,
625 ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
626 typelib_TypeDescription * pDestElementTD = 0;
627 TYPELIB_DANGER_GET(
628 &pDestElementTD,
629 ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
630
631 sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
632 uno_Sequence * pRet = 0;
633 uno_sequence_construct(
634 &pRet, aDestTD.get(), 0, nPos,
635 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
636 aRet.setValue( &pRet, aDestTD.get() );
637 uno_destructData(
638 &pRet, aDestTD.get(),
639 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
640 // decr ref count
641
642 char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
643 const char * pSourceElements =
644 (*(const uno_Sequence * const *)rVal.getValue())->elements;
645
646 while (nPos--)
647 {
648 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
649 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
650
651 Any aElement(
652 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
653
654 if (!uno_assignData(
655 pDestPos, pDestElementTD,
656 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
657 ? &aElement
658 : const_cast< void * >( aElement.getValue() )),
659 pDestElementTD,
660 reinterpret_cast< uno_QueryInterfaceFunc >(
661 cpp_queryInterface),
662 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
663 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
664 {
665 OSL_ASSERT( false );
666 }
667 }
668 TYPELIB_DANGER_RELEASE( pDestElementTD );
669 TYPELIB_DANGER_RELEASE( pSourceElementTD );
670 }
671 break;
672 }
673 // --- to ENUM ------------------------------------------------------------------------------
674 case TypeClass_ENUM:
675 {
676 TypeDescription aEnumTD( aDestType );
677 aEnumTD.makeComplete();
678 sal_Int32 nPos = -1;
679
680 if (aSourceClass==TypeClass_STRING)
681 {
682 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
683 {
684 if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase(
685 ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] ))
686 break;
687 }
688 }
689 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
690 aSourceClass!=TypeClass_BOOLEAN &&
691 aSourceClass!=TypeClass_CHAR)
692 {
693 sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff );
694 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
695 {
696 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
697 break;
698 }
699 }
700
701 if (nPos >= 0)
702 {
703 aRet.setValue(
704 &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos],
705 aEnumTD.get() );
706 }
707 else
708 {
709 throw CannotConvertException(
710 OUString(
711 RTL_CONSTASCII_USTRINGPARAM("value cannot be converted to demanded ENUM!") ),
712 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
713 }
714 break;
715 }
716
717 default:
718 // else simple type conversion possible?
719 try
720 {
721 aRet = convertToSimpleType( rVal, aDestinationClass );
722 }
723 catch (IllegalArgumentException &)
724 {
725 // ...FailReason::INVALID is thrown
726 }
727 }
728
729 if (aRet.hasValue())
730 return aRet;
731
732 throw CannotConvertException(
733 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
734 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
735 }
736
737 //--------------------------------------------------------------------------------------------------
convertToSimpleType(const Any & rVal,TypeClass aDestinationClass)738 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
739 throw( IllegalArgumentException, CannotConvertException, RuntimeException )
740 {
741 switch (aDestinationClass)
742 {
743 // only simple Conversion of _simple_ types
744 case TypeClass_INTERFACE:
745 case TypeClass_SERVICE:
746 case TypeClass_STRUCT:
747 case TypeClass_TYPEDEF:
748 case TypeClass_UNION:
749 case TypeClass_EXCEPTION:
750 case TypeClass_ARRAY:
751 case TypeClass_SEQUENCE:
752 case TypeClass_ENUM:
753 case TypeClass_UNKNOWN:
754 case TypeClass_MODULE:
755 throw IllegalArgumentException(
756 OUString( RTL_CONSTASCII_USTRINGPARAM("destination type is not simple!") ),
757 Reference< XInterface >(), (sal_Int16) 1 );
758 default:
759 break;
760 }
761
762 Type aSourceType = rVal.getValueType();
763 TypeClass aSourceClass = aSourceType.getTypeClass();
764 if (aDestinationClass == aSourceClass)
765 return rVal;
766
767 Any aRet;
768
769 // Convert to...
770 switch (aDestinationClass)
771 {
772 // --- to VOID ------------------------------------------------------------------------------
773 case TypeClass_VOID:
774 return Any();
775
776 // --- to ANY -------------------------------------------------------------------------------
777 case TypeClass_ANY:
778 return rVal;
779
780 // --- to BOOL ------------------------------------------------------------------------------
781 case TypeClass_BOOLEAN:
782 switch (aSourceClass)
783 {
784 default:
785 {
786 sal_Bool bTmp = (toDouble( rVal ) != 0.0);
787 aRet.setValue( &bTmp, getBooleanCppuType() );
788 }
789 case TypeClass_ENUM: // exclude enums
790 break;
791
792 case TypeClass_STRING:
793 {
794 const OUString & aStr = *(const OUString *)rVal.getValue();
795 if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("0") ) ||
796 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("false") ) ))
797 {
798 sal_Bool bFalse = sal_False;
799 aRet.setValue( &bFalse, getCppuBooleanType() );
800 }
801 else if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("1") ) ||
802 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("true") ) ))
803 {
804 sal_Bool bTrue = sal_True;
805 aRet.setValue( &bTrue, getCppuBooleanType() );
806 }
807 else
808 {
809 throw CannotConvertException(
810 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING has no boolean value!") ),
811 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
812 }
813 }
814 }
815 break;
816
817 // --- to CHAR, BYTE ------------------------------------------------------------------------
818 case TypeClass_CHAR:
819 {
820 if (aSourceClass==TypeClass_STRING)
821 {
822 if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char
823 aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() );
824 }
825 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
826 aSourceClass!=TypeClass_CHAR)
827 {
828 sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range
829 aRet.setValue( &cRet, ::getCharCppuType() );
830 }
831 break;
832 }
833 case TypeClass_BYTE:
834 aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) );
835 break;
836
837 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
838 case TypeClass_SHORT:
839 aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) );
840 break;
841 case TypeClass_UNSIGNED_SHORT:
842 aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) );
843 break;
844
845 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
846 case TypeClass_LONG:
847 aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) );
848 break;
849 case TypeClass_UNSIGNED_LONG:
850 aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) );
851 break;
852
853 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
854 case TypeClass_HYPER:
855 aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
856 break;
857 case TypeClass_UNSIGNED_HYPER:
858 aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) );
859 break;
860
861 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
862 case TypeClass_FLOAT:
863 aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
864 break;
865 case TypeClass_DOUBLE:
866 aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) );
867 break;
868
869 // --- to STRING ----------------------------------------------------------------------------
870 case TypeClass_STRING:
871 switch (aSourceClass)
872 {
873 case TypeClass_ENUM:
874 {
875 TypeDescription aEnumTD( aSourceType );
876 aEnumTD.makeComplete();
877 sal_Int32 nPos;
878 sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue();
879 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
880 {
881 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
882 break;
883 }
884 if (nPos >= 0)
885 {
886 aRet.setValue(
887 &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos],
888 ::getCppuType( (const OUString *)0 ) );
889 }
890 else
891 {
892 throw CannotConvertException(
893 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not ENUM!") ),
894 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
895 }
896 break;
897 }
898
899 case TypeClass_BOOLEAN:
900 aRet <<= OUString::createFromAscii( (*(sal_Bool *)rVal.getValue() ? "true" : "false") );
901 break;
902 case TypeClass_CHAR:
903 aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 );
904 break;
905
906 case TypeClass_BYTE:
907 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() );
908 break;
909 case TypeClass_SHORT:
910 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() );
911 break;
912 case TypeClass_UNSIGNED_SHORT:
913 aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() );
914 break;
915 case TypeClass_LONG:
916 aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() );
917 break;
918 case TypeClass_UNSIGNED_LONG:
919 aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() );
920 break;
921 case TypeClass_HYPER:
922 aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() );
923 break;
924 // case TypeClass_UNSIGNED_HYPER:
925 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
926 // break;
927 // handle unsigned hyper like double
928
929 default:
930 aRet <<= OUString::valueOf( toDouble( rVal ) );
931 }
932 break;
933
934 default:
935 OSL_ASSERT(false);
936 break;
937 }
938
939 if (aRet.hasValue())
940 return aRet;
941
942 throw CannotConvertException(
943 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
944 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
945 }
946 }
947
948 namespace stoc_services
949 {
950 //*************************************************************************
TypeConverter_Impl_CreateInstance(const Reference<XComponentContext> &)951 Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
952 const Reference< XComponentContext > & )
953 throw( RuntimeException )
954 {
955 static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
956 return s_ref;
957 }
958 }
959
960