Update ooo320-m1
[ooovba.git] / stoc / source / typeconv / convert.cxx
blob49a608471ffb4fed773d5a79b7b5e2e35523d000
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: convert.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include <osl/diagnose.h>
35 #include <cppuhelper/factory.hxx>
36 #include <cppuhelper/implementationentry.hxx>
37 #include <cppuhelper/implbase2.hxx>
39 #include <typelib/typedescription.hxx>
40 #include <uno/data.h>
42 #ifdef WNT
43 #include <cmath>
44 #else
45 #include <math.h>
46 #endif
47 #include <float.h>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
51 #include <com/sun/star/script/XTypeConverter.hpp>
52 #include <com/sun/star/script/FailReason.hpp>
53 #include <com/sun/star/container/XSet.hpp>
54 #include <com/sun/star/registry/XRegistryKey.hpp>
56 using namespace com::sun::star::uno;
57 using namespace com::sun::star::lang;
58 using namespace com::sun::star::script;
59 using namespace com::sun::star::registry;
60 using namespace cppu;
61 using namespace rtl;
62 using namespace osl;
64 #define SERVICENAME "com.sun.star.script.Converter"
65 #define IMPLNAME "com.sun.star.comp.stoc.TypeConverter"
68 extern rtl_StandardModuleCount g_moduleCount;
70 namespace stoc_services
72 Sequence< OUString > tcv_getSupportedServiceNames()
74 static Sequence < OUString > *pNames = 0;
75 if( ! pNames )
77 MutexGuard guard( Mutex::getGlobalMutex() );
78 if( !pNames )
80 static Sequence< OUString > seqNames(1);
81 seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
82 pNames = &seqNames;
85 return *pNames;
88 OUString tcv_getImplementationName()
90 static OUString *pImplName = 0;
91 if( ! pImplName )
93 MutexGuard guard( Mutex::getGlobalMutex() );
94 if( ! pImplName )
96 static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
97 pImplName = &implName;
100 return *pImplName;
104 namespace stoc_tcv
107 static const sal_uInt64 SAL_UINT64_MAX =
108 ((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
109 static const sal_Int64 SAL_INT64_MAX =
110 (sal_Int64)((((sal_uInt64)0x7fffffff) << 32) | (sal_uInt64)0xffffffff);
111 static const sal_Int64 SAL_INT64_MIN =
112 (sal_Int64)(((sal_uInt64)0x80000000) << 32);
114 /* MS Visual C++ no conversion from unsigned __int64 to double */
115 #ifdef _MSC_VER
116 static const double DOUBLE_SAL_UINT64_MAX = ((((double)SAL_INT64_MAX) * 2) + 1);
118 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () )
120 sal_uInt64 n2 = (n / 3);
121 n -= (2 * n2);
122 return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n);
124 #else
125 static const double DOUBLE_SAL_UINT64_MAX =
126 (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
128 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () )
130 return (double)n;
132 #endif
135 //--------------------------------------------------------------------------------------------------
136 static inline double round( double aVal )
138 sal_Bool bPos = (aVal >= 0.0); //
139 aVal = ::fabs( aVal );
140 double aUpper = ::ceil( aVal );
142 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
143 return (bPos ? aVal : -aVal);
146 //--------------------------------------------------------------------------------------------------
147 static sal_Bool getNumericValue( double & rfVal, const OUString & rStr )
149 double fRet = rStr.toDouble();
150 if (fRet == 0.0)
152 sal_Int32 nLen = rStr.getLength();
153 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
155 rfVal = 0.0;
156 return sal_True;
159 OUString trim( rStr.trim() );
161 // try hex
162 sal_Int32 nX = trim.indexOf( 'x' );
163 if (nX < 0)
164 nX = trim.indexOf( 'X' );
166 if (nX > 0 && trim[nX-1] == '0') // 0x
168 sal_Bool bNeg = sal_False;
169 switch (nX)
171 case 2: // (+|-)0x...
172 if (trim[0] == '-')
173 bNeg = sal_True;
174 else if (trim[0] != '+')
175 return sal_False;
176 case 1: // 0x...
177 break;
178 default:
179 return sal_False;
182 OUString aHexRest( trim.copy( nX+1 ) );
183 sal_Int64 nRet = aHexRest.toInt64( 16 );
185 if (nRet == 0)
187 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
189 if (aHexRest[nPos] != '0')
190 return sal_False;
194 rfVal = (bNeg ? -(double)nRet : (double)nRet);
195 return sal_True;
198 nLen = trim.getLength();
199 sal_Int32 nPos = 0;
201 // skip +/-
202 if (nLen && (trim[0] == '-' || trim[0] == '+'))
203 ++nPos;
205 while (nPos < nLen) // skip leading zeros
207 if (trim[nPos] != '0')
209 if (trim[nPos] != '.')
210 return sal_False;
211 ++nPos;
212 while (nPos < nLen) // skip trailing zeros
214 if (trim[nPos] != '0')
215 return sal_False;
216 ++nPos;
218 break;
220 ++nPos;
223 rfVal = fRet;
224 return sal_True;
227 //==================================================================================================
228 static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
230 sal_Int32 nLen = rStr.getLength();
231 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
233 rnVal = 0;
234 return sal_True;
237 OUString trim( rStr.trim() );
239 // try hex
240 sal_Int32 nX = trim.indexOf( 'x' );
241 if (nX < 0)
242 nX = trim.indexOf( 'X' );
244 if (nX >= 0)
246 if (nX > 0 && trim[nX-1] == '0') // 0x
248 sal_Bool bNeg = sal_False;
249 switch (nX)
251 case 2: // (+|-)0x...
252 if (trim[0] == '-')
253 bNeg = sal_True;
254 else if (trim[0] != '+')
255 return sal_False;
256 case 1: // 0x...
257 break;
258 default:
259 return sal_False;
262 OUString aHexRest( trim.copy( nX+1 ) );
263 sal_Int64 nRet = aHexRest.toInt64( 16 );
265 if (nRet == 0)
267 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
269 if (aHexRest[nPos] != '0')
270 return sal_False;
274 rnVal = (bNeg ? -nRet : nRet);
275 return sal_True;
277 return sal_False;
280 double fVal;
281 if (getNumericValue( fVal, rStr ) &&
282 fVal >= (double)SAL_INT64_MIN &&
283 fVal <= DOUBLE_SAL_UINT64_MAX)
285 rnVal = (sal_Int64)round( fVal );
286 return sal_True;
288 return sal_False;
291 //==================================================================================================
292 class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo >
294 // ...misc helpers...
295 sal_Int64 toHyper(
296 const Any& rAny, sal_Int64 min = SAL_INT64_MIN, sal_uInt64 max = SAL_UINT64_MAX )
297 throw( CannotConvertException );
298 double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const
299 throw( CannotConvertException );
301 public:
302 TypeConverter_Impl();
303 virtual ~TypeConverter_Impl();
305 // XServiceInfo
306 virtual OUString SAL_CALL getImplementationName() throw( RuntimeException );
307 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName)
308 throw( RuntimeException );
309 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
310 throw( RuntimeException );
312 // XTypeConverter
313 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType )
314 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
315 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType )
316 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
319 TypeConverter_Impl::TypeConverter_Impl()
321 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
324 TypeConverter_Impl::~TypeConverter_Impl()
326 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
329 // XServiceInfo
330 OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException )
332 return stoc_services::tcv_getImplementationName();
335 // XServiceInfo
336 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException )
338 Sequence< OUString > aSNL = getSupportedServiceNames();
339 const OUString * pArray = aSNL.getConstArray();
340 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
341 if( pArray[i] == ServiceName )
342 return sal_True;
343 return sal_False;
346 // XServiceInfo
347 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException )
349 return stoc_services::tcv_getSupportedServiceNames();
352 //--------------------------------------------------------------------------------------------------
353 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
354 throw( CannotConvertException )
356 sal_Int64 nRet;
357 TypeClass aDestinationClass = rAny.getValueTypeClass();
359 switch (aDestinationClass)
361 // ENUM
362 case TypeClass_ENUM:
363 nRet = *(sal_Int32 *)rAny.getValue();
364 break;
365 // BOOL
366 case TypeClass_BOOLEAN:
367 nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0);
368 break;
369 // CHAR, BYTE
370 case TypeClass_CHAR:
371 nRet = *(sal_Unicode *)rAny.getValue();
372 break;
373 case TypeClass_BYTE:
374 nRet = *(sal_Int8 *)rAny.getValue();
375 break;
376 // SHORT
377 case TypeClass_SHORT:
378 nRet = *(sal_Int16 *)rAny.getValue();
379 break;
380 // UNSIGNED SHORT
381 case TypeClass_UNSIGNED_SHORT:
382 nRet = *(sal_uInt16 *)rAny.getValue();
383 break;
384 // LONG
385 case TypeClass_LONG:
386 nRet = *(sal_Int32 *)rAny.getValue();
387 break;
388 // UNSIGNED LONG
389 case TypeClass_UNSIGNED_LONG:
390 nRet = *(sal_uInt32 *)rAny.getValue();
391 break;
392 // HYPER
393 case TypeClass_HYPER:
394 nRet = *(sal_Int64 *)rAny.getValue();
395 break;
396 // UNSIGNED HYPER
397 case TypeClass_UNSIGNED_HYPER:
399 nRet = *(sal_Int64 *)rAny.getValue();
400 if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound
401 (sal_uInt64)nRet <= max) // upper bound
403 return nRet;
405 throw CannotConvertException(
406 OUString( RTL_CONSTASCII_USTRINGPARAM("UNSIGNED HYPER out of range!") ),
407 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
410 // FLOAT, DOUBLE
411 case TypeClass_FLOAT:
413 double fVal = round( *(float *)rAny.getValue() );
414 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
415 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
417 return nRet;
419 throw CannotConvertException(
420 OUString( RTL_CONSTASCII_USTRINGPARAM("FLOAT out of range!") ),
421 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
423 case TypeClass_DOUBLE:
425 double fVal = round( *(double *)rAny.getValue() );
426 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
427 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
429 return nRet;
431 throw CannotConvertException(
432 OUString( RTL_CONSTASCII_USTRINGPARAM("DOUBLE out of range!") ),
433 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
436 // STRING
437 case TypeClass_STRING:
439 sal_Int64 fVal = SAL_CONST_INT64(0);
440 if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() ))
442 throw CannotConvertException(
443 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
444 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
446 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
447 if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max))
448 return nRet;
449 throw CannotConvertException(
450 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING value out of range!") ),
451 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
454 default:
455 throw CannotConvertException(
456 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
457 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
460 if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max))
461 return nRet;
462 throw CannotConvertException(
463 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
464 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
467 //--------------------------------------------------------------------------------------------------
468 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
469 throw( CannotConvertException )
471 double fRet;
472 TypeClass aDestinationClass = rAny.getValueTypeClass();
474 switch (aDestinationClass)
476 // ENUM
477 case TypeClass_ENUM:
478 fRet = *(sal_Int32 *)rAny.getValue();
479 break;
480 // BOOL
481 case TypeClass_BOOLEAN:
482 fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0);
483 break;
484 // CHAR, BYTE
485 case TypeClass_CHAR:
486 fRet = *(sal_Unicode *)rAny.getValue();
487 break;
488 case TypeClass_BYTE:
489 fRet = *(sal_Int8 *)rAny.getValue();
490 break;
491 // SHORT
492 case TypeClass_SHORT:
493 fRet = *(sal_Int16 *)rAny.getValue();
494 break;
495 // UNSIGNED SHORT
496 case TypeClass_UNSIGNED_SHORT:
497 fRet = *(sal_uInt16 *)rAny.getValue();
498 break;
499 // LONG
500 case TypeClass_LONG:
501 fRet = *(sal_Int32 *)rAny.getValue();
502 break;
503 // UNSIGNED LONG
504 case TypeClass_UNSIGNED_LONG:
505 fRet = *(sal_uInt32 *)rAny.getValue();
506 break;
507 // HYPER
508 case TypeClass_HYPER:
509 fRet = (double)*(sal_Int64 *)rAny.getValue();
510 break;
511 // UNSIGNED HYPER
512 case TypeClass_UNSIGNED_HYPER:
513 fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() );
514 break;
515 // FLOAT, DOUBLE
516 case TypeClass_FLOAT:
517 fRet = *(float *)rAny.getValue();
518 break;
519 case TypeClass_DOUBLE:
520 fRet = *(double *)rAny.getValue();
521 break;
523 // STRING
524 case TypeClass_STRING:
526 if (! getNumericValue( fRet, *(OUString *)rAny.getValue() ))
528 throw CannotConvertException(
529 OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ),
530 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
532 break;
535 default:
536 throw CannotConvertException(
537 OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ),
538 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
541 if (fRet >= min && fRet <= max)
542 return fRet;
543 throw CannotConvertException(
544 OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ),
545 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
548 //--------------------------------------------------------------------------------------------------
549 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
550 throw( IllegalArgumentException, CannotConvertException, RuntimeException)
552 Type aSourceType = rVal.getValueType();
553 if (aSourceType == aDestType)
554 return rVal;
556 TypeClass aSourceClass = aSourceType.getTypeClass();
557 TypeClass aDestinationClass = aDestType.getTypeClass();
559 Any aRet;
561 // convert to...
562 switch (aDestinationClass)
564 // --- to VOID ------------------------------------------------------------------------------
565 case TypeClass_VOID:
566 return Any();
567 // --- to ANY -------------------------------------------------------------------------------
568 case TypeClass_ANY:
569 return rVal;
571 // --- to STRUCT, UNION, EXCEPTION ----------------------------------------------------------
572 case TypeClass_STRUCT:
573 // case TypeClass_UNION: // xxx todo
574 case TypeClass_EXCEPTION:
576 // same types or destination type is derived source type?
577 TypeDescription aSourceTD( aSourceType );
578 TypeDescription aDestTD( aDestType );
579 if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
581 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
583 else
585 throw CannotConvertException(
586 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not of same or derived type!") ),
587 Reference< XInterface >(), aDestinationClass,
588 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
590 break;
592 // --- to INTERFACE -------------------------------------------------------------------------
593 case TypeClass_INTERFACE:
595 if (! rVal.hasValue())
597 // void -> interface (null)
598 void * null_ref = 0;
599 aRet.setValue( &null_ref, aDestType );
600 break;
603 if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
604 !*(XInterface * const *)rVal.getValue())
606 throw CannotConvertException(
607 OUString( RTL_CONSTASCII_USTRINGPARAM("value is no interface!") ),
608 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
610 if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
611 aDestType )).hasValue())
613 throw CannotConvertException(
614 OUString( RTL_CONSTASCII_USTRINGPARAM("value has no such interface!") ),
615 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
617 break;
619 // --- to SEQUENCE --------------------------------------------------------------------------
620 case TypeClass_SEQUENCE:
622 if (aSourceClass==TypeClass_SEQUENCE)
624 if( aSourceType == aDestType )
625 return rVal;
627 TypeDescription aSourceTD( aSourceType );
628 TypeDescription aDestTD( aDestType );
629 typelib_TypeDescription * pSourceElementTD = 0;
630 TYPELIB_DANGER_GET(
631 &pSourceElementTD,
632 ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
633 typelib_TypeDescription * pDestElementTD = 0;
634 TYPELIB_DANGER_GET(
635 &pDestElementTD,
636 ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
638 sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
639 uno_Sequence * pRet = 0;
640 uno_sequence_construct(
641 &pRet, aDestTD.get(), 0, nPos,
642 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
643 aRet.setValue( &pRet, aDestTD.get() );
644 uno_destructData(
645 &pRet, aDestTD.get(),
646 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
647 // decr ref count
649 char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
650 const char * pSourceElements =
651 (*(const uno_Sequence * const *)rVal.getValue())->elements;
653 while (nPos--)
655 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
656 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
658 Any aElement(
659 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
661 if (!uno_assignData(
662 pDestPos, pDestElementTD,
663 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
664 ? &aElement
665 : const_cast< void * >( aElement.getValue() )),
666 pDestElementTD,
667 reinterpret_cast< uno_QueryInterfaceFunc >(
668 cpp_queryInterface),
669 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
670 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
672 OSL_ASSERT( false );
675 TYPELIB_DANGER_RELEASE( pDestElementTD );
676 TYPELIB_DANGER_RELEASE( pSourceElementTD );
678 break;
680 // --- to ENUM ------------------------------------------------------------------------------
681 case TypeClass_ENUM:
683 TypeDescription aEnumTD( aDestType );
684 aEnumTD.makeComplete();
685 sal_Int32 nPos = -1;
687 if (aSourceClass==TypeClass_STRING)
689 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
691 if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase(
692 ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] ))
693 break;
696 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
697 aSourceClass!=TypeClass_BOOLEAN &&
698 aSourceClass!=TypeClass_CHAR)
700 sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff );
701 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
703 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
704 break;
708 if (nPos >= 0)
710 aRet.setValue(
711 &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos],
712 aEnumTD.get() );
714 else
716 throw CannotConvertException(
717 OUString(
718 RTL_CONSTASCII_USTRINGPARAM("value cannot be converted to demanded ENUM!") ),
719 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
721 break;
724 default:
725 // else simple type conversion possible?
728 aRet = convertToSimpleType( rVal, aDestinationClass );
730 catch (IllegalArgumentException &)
732 // ...FailReason::INVALID is thrown
736 if (aRet.hasValue())
737 return aRet;
739 throw CannotConvertException(
740 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
741 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
744 //--------------------------------------------------------------------------------------------------
745 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
746 throw( IllegalArgumentException, CannotConvertException, RuntimeException )
748 switch (aDestinationClass)
750 // only simple Conversion of _simple_ types
751 case TypeClass_INTERFACE:
752 case TypeClass_SERVICE:
753 case TypeClass_STRUCT:
754 case TypeClass_TYPEDEF:
755 case TypeClass_UNION:
756 case TypeClass_EXCEPTION:
757 case TypeClass_ARRAY:
758 case TypeClass_SEQUENCE:
759 case TypeClass_ENUM:
760 case TypeClass_UNKNOWN:
761 case TypeClass_MODULE:
762 throw IllegalArgumentException(
763 OUString( RTL_CONSTASCII_USTRINGPARAM("destination type is not simple!") ),
764 Reference< XInterface >(), (sal_Int16) 1 );
765 default:
766 break;
769 Type aSourceType = rVal.getValueType();
770 TypeClass aSourceClass = aSourceType.getTypeClass();
771 if (aDestinationClass == aSourceClass)
772 return rVal;
774 Any aRet;
776 // Convert to...
777 switch (aDestinationClass)
779 // --- to VOID ------------------------------------------------------------------------------
780 case TypeClass_VOID:
781 return Any();
783 // --- to ANY -------------------------------------------------------------------------------
784 case TypeClass_ANY:
785 return rVal;
787 // --- to BOOL ------------------------------------------------------------------------------
788 case TypeClass_BOOLEAN:
789 switch (aSourceClass)
791 default:
793 sal_Bool bTmp = (toDouble( rVal ) != 0.0);
794 aRet.setValue( &bTmp, getBooleanCppuType() );
796 case TypeClass_ENUM: // exclude enums
797 break;
799 case TypeClass_STRING:
801 const OUString & aStr = *(const OUString *)rVal.getValue();
802 if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("0") ) ||
803 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("false") ) ))
805 sal_Bool bFalse = sal_False;
806 aRet.setValue( &bFalse, getCppuBooleanType() );
808 else if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("1") ) ||
809 aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("true") ) ))
811 sal_Bool bTrue = sal_True;
812 aRet.setValue( &bTrue, getCppuBooleanType() );
814 else
816 throw CannotConvertException(
817 OUString( RTL_CONSTASCII_USTRINGPARAM("STRING has no boolean value!") ),
818 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
822 break;
824 // --- to CHAR, BYTE ------------------------------------------------------------------------
825 case TypeClass_CHAR:
827 if (aSourceClass==TypeClass_STRING)
829 if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char
830 aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() );
832 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
833 aSourceClass!=TypeClass_CHAR)
835 sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range
836 aRet.setValue( &cRet, ::getCharCppuType() );
838 break;
840 case TypeClass_BYTE:
841 aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) );
842 break;
844 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
845 case TypeClass_SHORT:
846 aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) );
847 break;
848 case TypeClass_UNSIGNED_SHORT:
849 aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) );
850 break;
852 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
853 case TypeClass_LONG:
854 aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) );
855 break;
856 case TypeClass_UNSIGNED_LONG:
857 aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) );
858 break;
860 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
861 case TypeClass_HYPER:
862 aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
863 break;
864 case TypeClass_UNSIGNED_HYPER:
865 aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) );
866 break;
868 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
869 case TypeClass_FLOAT:
870 aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
871 break;
872 case TypeClass_DOUBLE:
873 aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) );
874 break;
876 // --- to STRING ----------------------------------------------------------------------------
877 case TypeClass_STRING:
878 switch (aSourceClass)
880 case TypeClass_ENUM:
882 TypeDescription aEnumTD( aSourceType );
883 aEnumTD.makeComplete();
884 sal_Int32 nPos;
885 sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue();
886 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
888 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
889 break;
891 if (nPos >= 0)
893 aRet.setValue(
894 &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos],
895 ::getCppuType( (const OUString *)0 ) );
897 else
899 throw CannotConvertException(
900 OUString( RTL_CONSTASCII_USTRINGPARAM("value is not ENUM!") ),
901 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
903 break;
906 case TypeClass_BOOLEAN:
907 aRet <<= OUString::createFromAscii( (*(sal_Bool *)rVal.getValue() ? "true" : "false") );
908 break;
909 case TypeClass_CHAR:
910 aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 );
911 break;
913 case TypeClass_BYTE:
914 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() );
915 break;
916 case TypeClass_SHORT:
917 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() );
918 break;
919 case TypeClass_UNSIGNED_SHORT:
920 aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() );
921 break;
922 case TypeClass_LONG:
923 aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() );
924 break;
925 case TypeClass_UNSIGNED_LONG:
926 aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() );
927 break;
928 case TypeClass_HYPER:
929 aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() );
930 break;
931 // case TypeClass_UNSIGNED_HYPER:
932 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
933 // break;
934 // handle unsigned hyper like double
936 default:
937 aRet <<= OUString::valueOf( toDouble( rVal ) );
939 break;
941 default:
942 OSL_ASSERT(false);
943 break;
946 if (aRet.hasValue())
947 return aRet;
949 throw CannotConvertException(
950 OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
951 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
955 namespace stoc_services
957 //*************************************************************************
958 Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
959 const Reference< XComponentContext > & )
960 throw( RuntimeException )
962 static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
963 return s_ref;