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