fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / stoc / source / typeconv / convert.cxx
blob799bae3f8a7ec445b47573a411c90bcb716296a8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/diagnose.h>
22 #include <cppuhelper/factory.hxx>
23 #include <cppuhelper/implementationentry.hxx>
24 #include <cppuhelper/implbase2.hxx>
26 #include <typelib/typedescription.hxx>
27 #include <uno/data.h>
29 #ifdef WNT
30 #include <cmath>
31 #else
32 #include <math.h>
33 #endif
34 #include <float.h>
36 #include <com/sun/star/lang/XServiceInfo.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/script/XTypeConverter.hpp>
39 #include <com/sun/star/script/FailReason.hpp>
40 #include <com/sun/star/container/XSet.hpp>
41 #include <com/sun/star/registry/XRegistryKey.hpp>
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::lang;
45 using namespace com::sun::star::script;
46 using namespace com::sun::star::registry;
47 using namespace cppu;
48 using namespace osl;
49 #define SERVICENAME "com.sun.star.script.Converter"
50 #define IMPLNAME "com.sun.star.comp.stoc.TypeConverter"
52 namespace stoc_services
54 Sequence< OUString > tcv_getSupportedServiceNames()
56 Sequence< OUString > seqNames(1);
57 seqNames.getArray()[0] = OUString(SERVICENAME);
58 return seqNames;
61 OUString tcv_getImplementationName()
63 return OUString(IMPLNAME);
67 namespace stoc_tcv
70 static const sal_uInt64 SAL_UINT64_MAX =
71 ((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
72 static const sal_Int64 SAL_INT64_MAX =
73 (sal_Int64)((((sal_uInt64)0x7fffffff) << 32) | (sal_uInt64)0xffffffff);
74 static const sal_Int64 SAL_INT64_MIN =
75 (sal_Int64)(((sal_uInt64)0x80000000) << 32);
77 /* MS Visual C++ no conversion from unsigned __int64 to double */
78 #ifdef _MSC_VER
79 static const double DOUBLE_SAL_UINT64_MAX = ((((double)SAL_INT64_MAX) * 2) + 1);
81 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW(())
83 sal_uInt64 n2 = (n / 3);
84 n -= (2 * n2);
85 return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n);
87 #else
88 static const double DOUBLE_SAL_UINT64_MAX =
89 (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
91 static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW(())
93 return (double)n;
95 #endif
98 //--------------------------------------------------------------------------------------------------
99 static inline double round( double aVal )
101 sal_Bool bPos = (aVal >= 0.0); //
102 aVal = ::fabs( aVal );
103 double aUpper = ::ceil( aVal );
105 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
106 return (bPos ? aVal : -aVal);
109 //--------------------------------------------------------------------------------------------------
110 static sal_Bool getNumericValue( double & rfVal, const OUString & rStr )
112 double fRet = rStr.toDouble();
113 if (fRet == 0.0)
115 sal_Int32 nLen = rStr.getLength();
116 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
118 rfVal = 0.0;
119 return sal_True;
122 OUString trim( rStr.trim() );
124 // try hex
125 sal_Int32 nX = trim.indexOf( 'x' );
126 if (nX < 0)
127 nX = trim.indexOf( 'X' );
129 if (nX > 0 && trim[nX-1] == '0') // 0x
131 sal_Bool bNeg = sal_False;
132 switch (nX)
134 case 2: // (+|-)0x...
135 if (trim[0] == '-')
136 bNeg = sal_True;
137 else if (trim[0] != '+')
138 return sal_False;
139 case 1: // 0x...
140 break;
141 default:
142 return sal_False;
145 OUString aHexRest( trim.copy( nX+1 ) );
146 sal_Int64 nRet = aHexRest.toInt64( 16 );
148 if (nRet == 0)
150 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
152 if (aHexRest[nPos] != '0')
153 return sal_False;
157 rfVal = (bNeg ? -(double)nRet : (double)nRet);
158 return sal_True;
161 nLen = trim.getLength();
162 sal_Int32 nPos = 0;
164 // skip +/-
165 if (nLen && (trim[0] == '-' || trim[0] == '+'))
166 ++nPos;
168 while (nPos < nLen) // skip leading zeros
170 if (trim[nPos] != '0')
172 if (trim[nPos] != '.')
173 return sal_False;
174 ++nPos;
175 while (nPos < nLen) // skip trailing zeros
177 if (trim[nPos] != '0')
178 return sal_False;
179 ++nPos;
181 break;
183 ++nPos;
186 rfVal = fRet;
187 return sal_True;
190 //==================================================================================================
191 static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
193 sal_Int32 nLen = rStr.getLength();
194 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
196 rnVal = 0;
197 return sal_True;
200 OUString trim( rStr.trim() );
202 // try hex
203 sal_Int32 nX = trim.indexOf( 'x' );
204 if (nX < 0)
205 nX = trim.indexOf( 'X' );
207 if (nX >= 0)
209 if (nX > 0 && trim[nX-1] == '0') // 0x
211 sal_Bool bNeg = sal_False;
212 switch (nX)
214 case 2: // (+|-)0x...
215 if (trim[0] == '-')
216 bNeg = sal_True;
217 else if (trim[0] != '+')
218 return sal_False;
219 case 1: // 0x...
220 break;
221 default:
222 return sal_False;
225 OUString aHexRest( trim.copy( nX+1 ) );
226 sal_Int64 nRet = aHexRest.toInt64( 16 );
228 if (nRet == 0)
230 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
232 if (aHexRest[nPos] != '0')
233 return sal_False;
237 rnVal = (bNeg ? -nRet : nRet);
238 return sal_True;
240 return sal_False;
243 double fVal;
244 if (getNumericValue( fVal, rStr ) &&
245 fVal >= (double)SAL_INT64_MIN &&
246 fVal <= DOUBLE_SAL_UINT64_MAX)
248 rnVal = (sal_Int64)round( fVal );
249 return sal_True;
251 return sal_False;
254 //==================================================================================================
255 class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo >
257 // ...misc helpers...
258 sal_Int64 toHyper(
259 const Any& rAny, sal_Int64 min = SAL_INT64_MIN, sal_uInt64 max = SAL_UINT64_MAX )
260 throw( CannotConvertException );
261 double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const
262 throw( CannotConvertException );
264 public:
265 TypeConverter_Impl();
266 virtual ~TypeConverter_Impl();
268 // XServiceInfo
269 virtual OUString SAL_CALL getImplementationName() throw( RuntimeException );
270 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName)
271 throw( RuntimeException );
272 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void)
273 throw( RuntimeException );
275 // XTypeConverter
276 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType )
277 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
278 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType )
279 throw( IllegalArgumentException, CannotConvertException, RuntimeException);
282 TypeConverter_Impl::TypeConverter_Impl() {}
284 TypeConverter_Impl::~TypeConverter_Impl() {}
286 // XServiceInfo
287 OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException )
289 return stoc_services::tcv_getImplementationName();
292 // XServiceInfo
293 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException )
295 Sequence< OUString > aSNL = getSupportedServiceNames();
296 const OUString * pArray = aSNL.getConstArray();
297 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
298 if( pArray[i] == ServiceName )
299 return sal_True;
300 return sal_False;
303 // XServiceInfo
304 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException )
306 return stoc_services::tcv_getSupportedServiceNames();
309 //--------------------------------------------------------------------------------------------------
310 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
311 throw( CannotConvertException )
313 sal_Int64 nRet;
314 TypeClass aDestinationClass = rAny.getValueTypeClass();
316 switch (aDestinationClass)
318 // ENUM
319 case TypeClass_ENUM:
320 nRet = *(sal_Int32 *)rAny.getValue();
321 break;
322 // BOOL
323 case TypeClass_BOOLEAN:
324 nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0);
325 break;
326 // CHAR, BYTE
327 case TypeClass_CHAR:
328 nRet = *(sal_Unicode *)rAny.getValue();
329 break;
330 case TypeClass_BYTE:
331 nRet = *(sal_Int8 *)rAny.getValue();
332 break;
333 // SHORT
334 case TypeClass_SHORT:
335 nRet = *(sal_Int16 *)rAny.getValue();
336 break;
337 // UNSIGNED SHORT
338 case TypeClass_UNSIGNED_SHORT:
339 nRet = *(sal_uInt16 *)rAny.getValue();
340 break;
341 // LONG
342 case TypeClass_LONG:
343 nRet = *(sal_Int32 *)rAny.getValue();
344 break;
345 // UNSIGNED LONG
346 case TypeClass_UNSIGNED_LONG:
347 nRet = *(sal_uInt32 *)rAny.getValue();
348 break;
349 // HYPER
350 case TypeClass_HYPER:
351 nRet = *(sal_Int64 *)rAny.getValue();
352 break;
353 // UNSIGNED HYPER
354 case TypeClass_UNSIGNED_HYPER:
356 nRet = *(sal_Int64 *)rAny.getValue();
357 if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound
358 (sal_uInt64)nRet <= max) // upper bound
360 return nRet;
362 throw CannotConvertException(
363 OUString("UNSIGNED HYPER out of range!"),
364 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
367 // FLOAT, DOUBLE
368 case TypeClass_FLOAT:
370 double fVal = round( *(float *)rAny.getValue() );
371 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
372 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
374 return nRet;
376 throw CannotConvertException(
377 OUString("FLOAT out of range!"),
378 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
380 case TypeClass_DOUBLE:
382 double fVal = round( *(double *)rAny.getValue() );
383 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
384 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
386 return nRet;
388 throw CannotConvertException(
389 OUString("DOUBLE out of range!"),
390 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
393 // STRING
394 case TypeClass_STRING:
396 sal_Int64 fVal = SAL_CONST_INT64(0);
397 if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() ))
399 throw CannotConvertException(
400 OUString("invalid STRING value!"),
401 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
403 nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
404 if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max))
405 return nRet;
406 throw CannotConvertException(
407 OUString("STRING value out of range!"),
408 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
411 default:
412 throw CannotConvertException(
413 OUString("TYPE is not supported!"),
414 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
417 if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max))
418 return nRet;
419 throw CannotConvertException(
420 OUString("VALUE is out of range!"),
421 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
424 //--------------------------------------------------------------------------------------------------
425 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
426 throw( CannotConvertException )
428 double fRet;
429 TypeClass aDestinationClass = rAny.getValueTypeClass();
431 switch (aDestinationClass)
433 // ENUM
434 case TypeClass_ENUM:
435 fRet = *(sal_Int32 *)rAny.getValue();
436 break;
437 // BOOL
438 case TypeClass_BOOLEAN:
439 fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0);
440 break;
441 // CHAR, BYTE
442 case TypeClass_CHAR:
443 fRet = *(sal_Unicode *)rAny.getValue();
444 break;
445 case TypeClass_BYTE:
446 fRet = *(sal_Int8 *)rAny.getValue();
447 break;
448 // SHORT
449 case TypeClass_SHORT:
450 fRet = *(sal_Int16 *)rAny.getValue();
451 break;
452 // UNSIGNED SHORT
453 case TypeClass_UNSIGNED_SHORT:
454 fRet = *(sal_uInt16 *)rAny.getValue();
455 break;
456 // LONG
457 case TypeClass_LONG:
458 fRet = *(sal_Int32 *)rAny.getValue();
459 break;
460 // UNSIGNED LONG
461 case TypeClass_UNSIGNED_LONG:
462 fRet = *(sal_uInt32 *)rAny.getValue();
463 break;
464 // HYPER
465 case TypeClass_HYPER:
466 fRet = (double)*(sal_Int64 *)rAny.getValue();
467 break;
468 // UNSIGNED HYPER
469 case TypeClass_UNSIGNED_HYPER:
470 fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() );
471 break;
472 // FLOAT, DOUBLE
473 case TypeClass_FLOAT:
474 fRet = *(float *)rAny.getValue();
475 break;
476 case TypeClass_DOUBLE:
477 fRet = *(double *)rAny.getValue();
478 break;
480 // STRING
481 case TypeClass_STRING:
483 if (! getNumericValue( fRet, *(OUString *)rAny.getValue() ))
485 throw CannotConvertException(
486 OUString("invalid STRING value!"),
487 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
489 break;
492 default:
493 throw CannotConvertException(
494 OUString("TYPE is not supported!"),
495 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
498 if (fRet >= min && fRet <= max)
499 return fRet;
500 throw CannotConvertException(
501 OUString("VALUE is out of range!"),
502 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
505 //--------------------------------------------------------------------------------------------------
506 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
507 throw( IllegalArgumentException, CannotConvertException, RuntimeException)
509 Type aSourceType = rVal.getValueType();
510 if (aSourceType == aDestType)
511 return rVal;
513 TypeClass aSourceClass = aSourceType.getTypeClass();
514 TypeClass aDestinationClass = aDestType.getTypeClass();
516 Any aRet;
518 // convert to...
519 switch (aDestinationClass)
521 // --- to VOID ------------------------------------------------------------------------------
522 case TypeClass_VOID:
523 return Any();
524 // --- to ANY -------------------------------------------------------------------------------
525 case TypeClass_ANY:
526 return rVal;
528 // --- to STRUCT, UNION, EXCEPTION ----------------------------------------------------------
529 case TypeClass_STRUCT:
530 // case TypeClass_UNION: // xxx todo
531 case TypeClass_EXCEPTION:
533 // same types or destination type is derived source type?
534 TypeDescription aSourceTD( aSourceType );
535 TypeDescription aDestTD( aDestType );
536 if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
538 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
540 else
542 throw CannotConvertException(
543 OUString("value is not of same or derived type!"),
544 Reference< XInterface >(), aDestinationClass,
545 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
547 break;
549 // --- to INTERFACE -------------------------------------------------------------------------
550 case TypeClass_INTERFACE:
552 if (! rVal.hasValue())
554 // void -> interface (null)
555 void * null_ref = 0;
556 aRet.setValue( &null_ref, aDestType );
557 break;
560 if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
561 !*(XInterface * const *)rVal.getValue())
563 throw CannotConvertException(
564 OUString("value is no interface!"),
565 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
567 if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
568 aDestType )).hasValue())
570 throw CannotConvertException(
571 OUString("value has no such interface!"),
572 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
574 break;
576 // --- to SEQUENCE --------------------------------------------------------------------------
577 case TypeClass_SEQUENCE:
579 if (aSourceClass==TypeClass_SEQUENCE)
581 if( aSourceType == aDestType )
582 return rVal;
584 TypeDescription aSourceTD( aSourceType );
585 TypeDescription aDestTD( aDestType );
586 typelib_TypeDescription * pSourceElementTD = 0;
587 TYPELIB_DANGER_GET(
588 &pSourceElementTD,
589 ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
590 typelib_TypeDescription * pDestElementTD = 0;
591 TYPELIB_DANGER_GET(
592 &pDestElementTD,
593 ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
595 sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
596 uno_Sequence * pRet = 0;
597 uno_sequence_construct(
598 &pRet, aDestTD.get(), 0, nPos,
599 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
600 aRet.setValue( &pRet, aDestTD.get() );
601 uno_destructData(
602 &pRet, aDestTD.get(),
603 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
604 // decr ref count
606 char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
607 const char * pSourceElements =
608 (*(const uno_Sequence * const *)rVal.getValue())->elements;
610 while (nPos--)
612 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
613 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
615 Any aElement(
616 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
618 if (!uno_assignData(
619 pDestPos, pDestElementTD,
620 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
621 ? &aElement
622 : const_cast< void * >( aElement.getValue() )),
623 pDestElementTD,
624 reinterpret_cast< uno_QueryInterfaceFunc >(
625 cpp_queryInterface),
626 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
627 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
629 OSL_ASSERT( false );
632 TYPELIB_DANGER_RELEASE( pDestElementTD );
633 TYPELIB_DANGER_RELEASE( pSourceElementTD );
635 break;
637 // --- to ENUM ------------------------------------------------------------------------------
638 case TypeClass_ENUM:
640 TypeDescription aEnumTD( aDestType );
641 aEnumTD.makeComplete();
642 sal_Int32 nPos = -1;
644 if (aSourceClass==TypeClass_STRING)
646 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
648 if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase(
649 ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] ))
650 break;
653 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
654 aSourceClass!=TypeClass_BOOLEAN &&
655 aSourceClass!=TypeClass_CHAR)
657 sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff );
658 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
660 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
661 break;
665 if (nPos >= 0)
667 aRet.setValue(
668 &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos],
669 aEnumTD.get() );
671 else
673 throw CannotConvertException(
674 OUString("value cannot be converted to demanded ENUM!"),
675 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
677 break;
680 default:
681 // else simple type conversion possible?
684 aRet = convertToSimpleType( rVal, aDestinationClass );
686 catch (IllegalArgumentException &)
688 // ...FailReason::INVALID is thrown
692 if (aRet.hasValue())
693 return aRet;
695 throw CannotConvertException(
696 OUString("conversion not possible!"),
697 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
700 //--------------------------------------------------------------------------------------------------
701 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
702 throw( IllegalArgumentException, CannotConvertException, RuntimeException )
704 switch (aDestinationClass)
706 // only simple Conversion of _simple_ types
707 case TypeClass_INTERFACE:
708 case TypeClass_SERVICE:
709 case TypeClass_STRUCT:
710 case TypeClass_TYPEDEF:
711 case TypeClass_UNION:
712 case TypeClass_EXCEPTION:
713 case TypeClass_ARRAY:
714 case TypeClass_SEQUENCE:
715 case TypeClass_ENUM:
716 case TypeClass_UNKNOWN:
717 case TypeClass_MODULE:
718 throw IllegalArgumentException(
719 OUString("destination type is not simple!"),
720 Reference< XInterface >(), (sal_Int16) 1 );
721 default:
722 break;
725 Type aSourceType = rVal.getValueType();
726 TypeClass aSourceClass = aSourceType.getTypeClass();
727 if (aDestinationClass == aSourceClass)
728 return rVal;
730 Any aRet;
732 // Convert to...
733 switch (aDestinationClass)
735 // --- to VOID ------------------------------------------------------------------------------
736 case TypeClass_VOID:
737 return Any();
739 // --- to ANY -------------------------------------------------------------------------------
740 case TypeClass_ANY:
741 return rVal;
743 // --- to BOOL ------------------------------------------------------------------------------
744 case TypeClass_BOOLEAN:
745 switch (aSourceClass)
747 default:
749 sal_Bool bTmp = (toDouble( rVal ) != 0.0);
750 aRet.setValue( &bTmp, getBooleanCppuType() );
752 case TypeClass_ENUM: // exclude enums
753 break;
755 case TypeClass_STRING:
757 const OUString & aStr = *(const OUString *)rVal.getValue();
758 if ( aStr == "0" || aStr.equalsIgnoreAsciiCase( OUString("false") ))
760 sal_Bool bFalse = sal_False;
761 aRet.setValue( &bFalse, getCppuBooleanType() );
763 else if ( aStr == "1" || aStr.equalsIgnoreAsciiCase( OUString("true") ))
765 sal_Bool bTrue = sal_True;
766 aRet.setValue( &bTrue, getCppuBooleanType() );
768 else
770 throw CannotConvertException(
771 OUString("STRING has no boolean value!"),
772 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
776 break;
778 // --- to CHAR, BYTE ------------------------------------------------------------------------
779 case TypeClass_CHAR:
781 if (aSourceClass==TypeClass_STRING)
783 if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char
784 aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() );
786 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
787 aSourceClass!=TypeClass_CHAR)
789 sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range
790 aRet.setValue( &cRet, ::getCharCppuType() );
792 break;
794 case TypeClass_BYTE:
795 aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) );
796 break;
798 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
799 case TypeClass_SHORT:
800 aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) );
801 break;
802 case TypeClass_UNSIGNED_SHORT:
803 aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) );
804 break;
806 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
807 case TypeClass_LONG:
808 aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) );
809 break;
810 case TypeClass_UNSIGNED_LONG:
811 aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) );
812 break;
814 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
815 case TypeClass_HYPER:
816 aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
817 break;
818 case TypeClass_UNSIGNED_HYPER:
819 aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) );
820 break;
822 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
823 case TypeClass_FLOAT:
824 aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
825 break;
826 case TypeClass_DOUBLE:
827 aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) );
828 break;
830 // --- to STRING ----------------------------------------------------------------------------
831 case TypeClass_STRING:
832 switch (aSourceClass)
834 case TypeClass_ENUM:
836 TypeDescription aEnumTD( aSourceType );
837 aEnumTD.makeComplete();
838 sal_Int32 nPos;
839 sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue();
840 for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
842 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
843 break;
845 if (nPos >= 0)
847 aRet.setValue(
848 &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos],
849 ::getCppuType( (const OUString *)0 ) );
851 else
853 throw CannotConvertException(
854 OUString("value is not ENUM!"),
855 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
857 break;
860 case TypeClass_BOOLEAN:
861 aRet <<= (*(sal_Bool *)rVal.getValue()) ?
862 OUString("true") :
863 OUString("false");
864 break;
865 case TypeClass_CHAR:
866 aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 );
867 break;
869 case TypeClass_BYTE:
870 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() );
871 break;
872 case TypeClass_SHORT:
873 aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() );
874 break;
875 case TypeClass_UNSIGNED_SHORT:
876 aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() );
877 break;
878 case TypeClass_LONG:
879 aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() );
880 break;
881 case TypeClass_UNSIGNED_LONG:
882 aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() );
883 break;
884 case TypeClass_HYPER:
885 aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() );
886 break;
887 // case TypeClass_UNSIGNED_HYPER:
888 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
889 // break;
890 // handle unsigned hyper like double
892 default:
893 aRet <<= OUString::valueOf( toDouble( rVal ) );
895 break;
897 default:
898 OSL_ASSERT(false);
899 break;
902 if (aRet.hasValue())
903 return aRet;
905 throw CannotConvertException(
906 OUString("conversion not possible!"),
907 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
911 namespace stoc_services
913 //*************************************************************************
914 Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
915 SAL_UNUSED_PARAMETER const Reference< XComponentContext > & )
916 throw( RuntimeException )
918 static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
919 return s_ref;
923 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */