xref: /AOO41X/main/stoc/source/typeconv/convert.cxx (revision 647a425c57429e1e89af1c7acf2de6af6f1bb730)
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