xref: /trunk/main/stoc/source/typeconv/convert.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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