| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_stoc.hxx" |
| |
| #include <osl/diagnose.h> |
| #include <cppuhelper/factory.hxx> |
| #include <cppuhelper/implementationentry.hxx> |
| #include <cppuhelper/implbase2.hxx> |
| |
| #include <typelib/typedescription.hxx> |
| #include <uno/data.h> |
| |
| #ifdef WNT |
| #include <cmath> |
| #else |
| #include <math.h> |
| #endif |
| #include <float.h> |
| |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/script/XTypeConverter.hpp> |
| #include <com/sun/star/script/FailReason.hpp> |
| #include <com/sun/star/container/XSet.hpp> |
| #include <com/sun/star/registry/XRegistryKey.hpp> |
| |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::script; |
| using namespace com::sun::star::registry; |
| using namespace cppu; |
| using namespace rtl; |
| using namespace osl; |
| |
| #define SERVICENAME "com.sun.star.script.Converter" |
| #define IMPLNAME "com.sun.star.comp.stoc.TypeConverter" |
| |
| |
| extern rtl_StandardModuleCount g_moduleCount; |
| |
| namespace stoc_services |
| { |
| Sequence< OUString > tcv_getSupportedServiceNames() |
| { |
| static Sequence < OUString > *pNames = 0; |
| if( ! pNames ) |
| { |
| MutexGuard guard( Mutex::getGlobalMutex() ); |
| if( !pNames ) |
| { |
| static Sequence< OUString > seqNames(1); |
| seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); |
| pNames = &seqNames; |
| } |
| } |
| return *pNames; |
| } |
| |
| OUString tcv_getImplementationName() |
| { |
| static OUString *pImplName = 0; |
| if( ! pImplName ) |
| { |
| MutexGuard guard( Mutex::getGlobalMutex() ); |
| if( ! pImplName ) |
| { |
| static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); |
| pImplName = &implName; |
| } |
| } |
| return *pImplName; |
| } |
| } |
| |
| namespace stoc_tcv |
| { |
| |
| static const sal_uInt64 SAL_UINT64_MAX = |
| ((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff); |
| static const sal_Int64 SAL_INT64_MAX = |
| (sal_Int64)((((sal_uInt64)0x7fffffff) << 32) | (sal_uInt64)0xffffffff); |
| static const sal_Int64 SAL_INT64_MIN = |
| (sal_Int64)(((sal_uInt64)0x80000000) << 32); |
| |
| /* MS Visual C++ no conversion from unsigned __int64 to double */ |
| #ifdef _MSC_VER |
| static const double DOUBLE_SAL_UINT64_MAX = ((((double)SAL_INT64_MAX) * 2) + 1); |
| |
| static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () ) |
| { |
| sal_uInt64 n2 = (n / 3); |
| n -= (2 * n2); |
| return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n); |
| } |
| #else |
| static const double DOUBLE_SAL_UINT64_MAX = |
| (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff); |
| |
| static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () ) |
| { |
| return (double)n; |
| } |
| #endif |
| |
| |
| //-------------------------------------------------------------------------------------------------- |
| static inline double round( double aVal ) |
| { |
| sal_Bool bPos = (aVal >= 0.0); // |
| aVal = ::fabs( aVal ); |
| double aUpper = ::ceil( aVal ); |
| |
| aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0); |
| return (bPos ? aVal : -aVal); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| static sal_Bool getNumericValue( double & rfVal, const OUString & rStr ) |
| { |
| double fRet = rStr.toDouble(); |
| if (fRet == 0.0) |
| { |
| sal_Int32 nLen = rStr.getLength(); |
| if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case |
| { |
| rfVal = 0.0; |
| return sal_True; |
| } |
| |
| OUString trim( rStr.trim() ); |
| |
| // try hex |
| sal_Int32 nX = trim.indexOf( 'x' ); |
| if (nX < 0) |
| nX = trim.indexOf( 'X' ); |
| |
| if (nX > 0 && trim[nX-1] == '0') // 0x |
| { |
| sal_Bool bNeg = sal_False; |
| switch (nX) |
| { |
| case 2: // (+|-)0x... |
| if (trim[0] == '-') |
| bNeg = sal_True; |
| else if (trim[0] != '+') |
| return sal_False; |
| case 1: // 0x... |
| break; |
| default: |
| return sal_False; |
| } |
| |
| OUString aHexRest( trim.copy( nX+1 ) ); |
| sal_Int64 nRet = aHexRest.toInt64( 16 ); |
| |
| if (nRet == 0) |
| { |
| for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; ) |
| { |
| if (aHexRest[nPos] != '0') |
| return sal_False; |
| } |
| } |
| |
| rfVal = (bNeg ? -(double)nRet : (double)nRet); |
| return sal_True; |
| } |
| |
| nLen = trim.getLength(); |
| sal_Int32 nPos = 0; |
| |
| // skip +/- |
| if (nLen && (trim[0] == '-' || trim[0] == '+')) |
| ++nPos; |
| |
| while (nPos < nLen) // skip leading zeros |
| { |
| if (trim[nPos] != '0') |
| { |
| if (trim[nPos] != '.') |
| return sal_False; |
| ++nPos; |
| while (nPos < nLen) // skip trailing zeros |
| { |
| if (trim[nPos] != '0') |
| return sal_False; |
| ++nPos; |
| } |
| break; |
| } |
| ++nPos; |
| } |
| } |
| rfVal = fRet; |
| return sal_True; |
| } |
| |
| //================================================================================================== |
| static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr ) |
| { |
| sal_Int32 nLen = rStr.getLength(); |
| if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case |
| { |
| rnVal = 0; |
| return sal_True; |
| } |
| |
| OUString trim( rStr.trim() ); |
| |
| // try hex |
| sal_Int32 nX = trim.indexOf( 'x' ); |
| if (nX < 0) |
| nX = trim.indexOf( 'X' ); |
| |
| if (nX >= 0) |
| { |
| if (nX > 0 && trim[nX-1] == '0') // 0x |
| { |
| sal_Bool bNeg = sal_False; |
| switch (nX) |
| { |
| case 2: // (+|-)0x... |
| if (trim[0] == '-') |
| bNeg = sal_True; |
| else if (trim[0] != '+') |
| return sal_False; |
| case 1: // 0x... |
| break; |
| default: |
| return sal_False; |
| } |
| |
| OUString aHexRest( trim.copy( nX+1 ) ); |
| sal_Int64 nRet = aHexRest.toInt64( 16 ); |
| |
| if (nRet == 0) |
| { |
| for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; ) |
| { |
| if (aHexRest[nPos] != '0') |
| return sal_False; |
| } |
| } |
| |
| rnVal = (bNeg ? -nRet : nRet); |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| double fVal; |
| if (getNumericValue( fVal, rStr ) && |
| fVal >= (double)SAL_INT64_MIN && |
| fVal <= DOUBLE_SAL_UINT64_MAX) |
| { |
| rnVal = (sal_Int64)round( fVal ); |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| //================================================================================================== |
| class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo > |
| { |
| // ...misc helpers... |
| sal_Int64 toHyper( |
| const Any& rAny, sal_Int64 min = SAL_INT64_MIN, sal_uInt64 max = SAL_UINT64_MAX ) |
| throw( CannotConvertException ); |
| double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const |
| throw( CannotConvertException ); |
| |
| public: |
| TypeConverter_Impl(); |
| virtual ~TypeConverter_Impl(); |
| |
| // XServiceInfo |
| virtual OUString SAL_CALL getImplementationName() throw( RuntimeException ); |
| virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) |
| throw( RuntimeException ); |
| virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) |
| throw( RuntimeException ); |
| |
| // XTypeConverter |
| virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType ) |
| throw( IllegalArgumentException, CannotConvertException, RuntimeException); |
| virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType ) |
| throw( IllegalArgumentException, CannotConvertException, RuntimeException); |
| }; |
| |
| TypeConverter_Impl::TypeConverter_Impl() |
| { |
| g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); |
| } |
| |
| TypeConverter_Impl::~TypeConverter_Impl() |
| { |
| g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); |
| } |
| |
| // XServiceInfo |
| OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException ) |
| { |
| return stoc_services::tcv_getImplementationName(); |
| } |
| |
| // XServiceInfo |
| sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException ) |
| { |
| Sequence< OUString > aSNL = getSupportedServiceNames(); |
| const OUString * pArray = aSNL.getConstArray(); |
| for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) |
| if( pArray[i] == ServiceName ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| // XServiceInfo |
| Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException ) |
| { |
| return stoc_services::tcv_getSupportedServiceNames(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max ) |
| throw( CannotConvertException ) |
| { |
| sal_Int64 nRet; |
| TypeClass aDestinationClass = rAny.getValueTypeClass(); |
| |
| switch (aDestinationClass) |
| { |
| // ENUM |
| case TypeClass_ENUM: |
| nRet = *(sal_Int32 *)rAny.getValue(); |
| break; |
| // BOOL |
| case TypeClass_BOOLEAN: |
| nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0); |
| break; |
| // CHAR, BYTE |
| case TypeClass_CHAR: |
| nRet = *(sal_Unicode *)rAny.getValue(); |
| break; |
| case TypeClass_BYTE: |
| nRet = *(sal_Int8 *)rAny.getValue(); |
| break; |
| // SHORT |
| case TypeClass_SHORT: |
| nRet = *(sal_Int16 *)rAny.getValue(); |
| break; |
| // UNSIGNED SHORT |
| case TypeClass_UNSIGNED_SHORT: |
| nRet = *(sal_uInt16 *)rAny.getValue(); |
| break; |
| // LONG |
| case TypeClass_LONG: |
| nRet = *(sal_Int32 *)rAny.getValue(); |
| break; |
| // UNSIGNED LONG |
| case TypeClass_UNSIGNED_LONG: |
| nRet = *(sal_uInt32 *)rAny.getValue(); |
| break; |
| // HYPER |
| case TypeClass_HYPER: |
| nRet = *(sal_Int64 *)rAny.getValue(); |
| break; |
| // UNSIGNED HYPER |
| case TypeClass_UNSIGNED_HYPER: |
| { |
| nRet = *(sal_Int64 *)rAny.getValue(); |
| if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound |
| (sal_uInt64)nRet <= max) // upper bound |
| { |
| return nRet; |
| } |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("UNSIGNED HYPER out of range!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| |
| // FLOAT, DOUBLE |
| case TypeClass_FLOAT: |
| { |
| double fVal = round( *(float *)rAny.getValue() ); |
| nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); |
| if (fVal >= min && fVal <= unsigned_int64_to_double( max )) |
| { |
| return nRet; |
| } |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("FLOAT out of range!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| case TypeClass_DOUBLE: |
| { |
| double fVal = round( *(double *)rAny.getValue() ); |
| nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); |
| if (fVal >= min && fVal <= unsigned_int64_to_double( max )) |
| { |
| return nRet; |
| } |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("DOUBLE out of range!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| |
| // STRING |
| case TypeClass_STRING: |
| { |
| sal_Int64 fVal = SAL_CONST_INT64(0); |
| if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() )) |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 ); |
| } |
| nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); |
| if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max)) |
| return nRet; |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("STRING value out of range!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| |
| default: |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 ); |
| } |
| |
| if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max)) |
| return nRet; |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const |
| throw( CannotConvertException ) |
| { |
| double fRet; |
| TypeClass aDestinationClass = rAny.getValueTypeClass(); |
| |
| switch (aDestinationClass) |
| { |
| // ENUM |
| case TypeClass_ENUM: |
| fRet = *(sal_Int32 *)rAny.getValue(); |
| break; |
| // BOOL |
| case TypeClass_BOOLEAN: |
| fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0); |
| break; |
| // CHAR, BYTE |
| case TypeClass_CHAR: |
| fRet = *(sal_Unicode *)rAny.getValue(); |
| break; |
| case TypeClass_BYTE: |
| fRet = *(sal_Int8 *)rAny.getValue(); |
| break; |
| // SHORT |
| case TypeClass_SHORT: |
| fRet = *(sal_Int16 *)rAny.getValue(); |
| break; |
| // UNSIGNED SHORT |
| case TypeClass_UNSIGNED_SHORT: |
| fRet = *(sal_uInt16 *)rAny.getValue(); |
| break; |
| // LONG |
| case TypeClass_LONG: |
| fRet = *(sal_Int32 *)rAny.getValue(); |
| break; |
| // UNSIGNED LONG |
| case TypeClass_UNSIGNED_LONG: |
| fRet = *(sal_uInt32 *)rAny.getValue(); |
| break; |
| // HYPER |
| case TypeClass_HYPER: |
| fRet = (double)*(sal_Int64 *)rAny.getValue(); |
| break; |
| // UNSIGNED HYPER |
| case TypeClass_UNSIGNED_HYPER: |
| fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() ); |
| break; |
| // FLOAT, DOUBLE |
| case TypeClass_FLOAT: |
| fRet = *(float *)rAny.getValue(); |
| break; |
| case TypeClass_DOUBLE: |
| fRet = *(double *)rAny.getValue(); |
| break; |
| |
| // STRING |
| case TypeClass_STRING: |
| { |
| if (! getNumericValue( fRet, *(OUString *)rAny.getValue() )) |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ), |
| Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 ); |
| } |
| break; |
| } |
| |
| default: |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 ); |
| } |
| |
| if (fRet >= min && fRet <= max) |
| return fRet; |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType ) |
| throw( IllegalArgumentException, CannotConvertException, RuntimeException) |
| { |
| Type aSourceType = rVal.getValueType(); |
| if (aSourceType == aDestType) |
| return rVal; |
| |
| TypeClass aSourceClass = aSourceType.getTypeClass(); |
| TypeClass aDestinationClass = aDestType.getTypeClass(); |
| |
| Any aRet; |
| |
| // convert to... |
| switch (aDestinationClass) |
| { |
| // --- to VOID ------------------------------------------------------------------------------ |
| case TypeClass_VOID: |
| return Any(); |
| // --- to ANY ------------------------------------------------------------------------------- |
| case TypeClass_ANY: |
| return rVal; |
| |
| // --- to STRUCT, UNION, EXCEPTION ---------------------------------------------------------- |
| case TypeClass_STRUCT: |
| // case TypeClass_UNION: // xxx todo |
| case TypeClass_EXCEPTION: |
| { |
| // same types or destination type is derived source type? |
| TypeDescription aSourceTD( aSourceType ); |
| TypeDescription aDestTD( aDestType ); |
| if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() )) |
| { |
| aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT. |
| } |
| else |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("value is not of same or derived type!") ), |
| Reference< XInterface >(), aDestinationClass, |
| FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 ); |
| } |
| break; |
| } |
| // --- to INTERFACE ------------------------------------------------------------------------- |
| case TypeClass_INTERFACE: |
| { |
| if (! rVal.hasValue()) |
| { |
| // void -> interface (null) |
| void * null_ref = 0; |
| aRet.setValue( &null_ref, aDestType ); |
| break; |
| } |
| |
| if (rVal.getValueTypeClass() != TypeClass_INTERFACE || |
| !*(XInterface * const *)rVal.getValue()) |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("value is no interface!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 ); |
| } |
| if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface( |
| aDestType )).hasValue()) |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("value has no such interface!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 ); |
| } |
| break; |
| } |
| // --- to SEQUENCE -------------------------------------------------------------------------- |
| case TypeClass_SEQUENCE: |
| { |
| if (aSourceClass==TypeClass_SEQUENCE) |
| { |
| if( aSourceType == aDestType ) |
| return rVal; |
| |
| TypeDescription aSourceTD( aSourceType ); |
| TypeDescription aDestTD( aDestType ); |
| typelib_TypeDescription * pSourceElementTD = 0; |
| TYPELIB_DANGER_GET( |
| &pSourceElementTD, |
| ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType ); |
| typelib_TypeDescription * pDestElementTD = 0; |
| TYPELIB_DANGER_GET( |
| &pDestElementTD, |
| ((typelib_IndirectTypeDescription *)aDestTD.get())->pType ); |
| |
| sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements; |
| uno_Sequence * pRet = 0; |
| uno_sequence_construct( |
| &pRet, aDestTD.get(), 0, nPos, |
| reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); |
| aRet.setValue( &pRet, aDestTD.get() ); |
| uno_destructData( |
| &pRet, aDestTD.get(), |
| reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); |
| // decr ref count |
| |
| char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements; |
| const char * pSourceElements = |
| (*(const uno_Sequence * const *)rVal.getValue())->elements; |
| |
| while (nPos--) |
| { |
| char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize); |
| const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize); |
| |
| Any aElement( |
| convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) ); |
| |
| if (!uno_assignData( |
| pDestPos, pDestElementTD, |
| (pDestElementTD->eTypeClass == typelib_TypeClass_ANY |
| ? &aElement |
| : const_cast< void * >( aElement.getValue() )), |
| pDestElementTD, |
| reinterpret_cast< uno_QueryInterfaceFunc >( |
| cpp_queryInterface), |
| reinterpret_cast< uno_AcquireFunc >(cpp_acquire), |
| reinterpret_cast< uno_ReleaseFunc >(cpp_release) )) |
| { |
| OSL_ASSERT( false ); |
| } |
| } |
| TYPELIB_DANGER_RELEASE( pDestElementTD ); |
| TYPELIB_DANGER_RELEASE( pSourceElementTD ); |
| } |
| break; |
| } |
| // --- to ENUM ------------------------------------------------------------------------------ |
| case TypeClass_ENUM: |
| { |
| TypeDescription aEnumTD( aDestType ); |
| aEnumTD.makeComplete(); |
| sal_Int32 nPos = -1; |
| |
| if (aSourceClass==TypeClass_STRING) |
| { |
| for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) |
| { |
| if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase( |
| ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] )) |
| break; |
| } |
| } |
| else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper() |
| aSourceClass!=TypeClass_BOOLEAN && |
| aSourceClass!=TypeClass_CHAR) |
| { |
| sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ); |
| for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) |
| { |
| if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos]) |
| break; |
| } |
| } |
| |
| if (nPos >= 0) |
| { |
| aRet.setValue( |
| &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos], |
| aEnumTD.get() ); |
| } |
| else |
| { |
| throw CannotConvertException( |
| OUString( |
| RTL_CONSTASCII_USTRINGPARAM("value cannot be converted to demanded ENUM!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 ); |
| } |
| break; |
| } |
| |
| default: |
| // else simple type conversion possible? |
| try |
| { |
| aRet = convertToSimpleType( rVal, aDestinationClass ); |
| } |
| catch (IllegalArgumentException &) |
| { |
| // ...FailReason::INVALID is thrown |
| } |
| } |
| |
| if (aRet.hasValue()) |
| return aRet; |
| |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 ); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass ) |
| throw( IllegalArgumentException, CannotConvertException, RuntimeException ) |
| { |
| switch (aDestinationClass) |
| { |
| // only simple Conversion of _simple_ types |
| case TypeClass_INTERFACE: |
| case TypeClass_SERVICE: |
| case TypeClass_STRUCT: |
| case TypeClass_TYPEDEF: |
| case TypeClass_UNION: |
| case TypeClass_EXCEPTION: |
| case TypeClass_ARRAY: |
| case TypeClass_SEQUENCE: |
| case TypeClass_ENUM: |
| case TypeClass_UNKNOWN: |
| case TypeClass_MODULE: |
| throw IllegalArgumentException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("destination type is not simple!") ), |
| Reference< XInterface >(), (sal_Int16) 1 ); |
| default: |
| break; |
| } |
| |
| Type aSourceType = rVal.getValueType(); |
| TypeClass aSourceClass = aSourceType.getTypeClass(); |
| if (aDestinationClass == aSourceClass) |
| return rVal; |
| |
| Any aRet; |
| |
| // Convert to... |
| switch (aDestinationClass) |
| { |
| // --- to VOID ------------------------------------------------------------------------------ |
| case TypeClass_VOID: |
| return Any(); |
| |
| // --- to ANY ------------------------------------------------------------------------------- |
| case TypeClass_ANY: |
| return rVal; |
| |
| // --- to BOOL ------------------------------------------------------------------------------ |
| case TypeClass_BOOLEAN: |
| switch (aSourceClass) |
| { |
| default: |
| { |
| sal_Bool bTmp = (toDouble( rVal ) != 0.0); |
| aRet.setValue( &bTmp, getBooleanCppuType() ); |
| } |
| case TypeClass_ENUM: // exclude enums |
| break; |
| |
| case TypeClass_STRING: |
| { |
| const OUString & aStr = *(const OUString *)rVal.getValue(); |
| if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("0") ) || |
| aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("false") ) )) |
| { |
| sal_Bool bFalse = sal_False; |
| aRet.setValue( &bFalse, getCppuBooleanType() ); |
| } |
| else if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("1") ) || |
| aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("true") ) )) |
| { |
| sal_Bool bTrue = sal_True; |
| aRet.setValue( &bTrue, getCppuBooleanType() ); |
| } |
| else |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("STRING has no boolean value!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 ); |
| } |
| } |
| } |
| break; |
| |
| // --- to CHAR, BYTE ------------------------------------------------------------------------ |
| case TypeClass_CHAR: |
| { |
| if (aSourceClass==TypeClass_STRING) |
| { |
| if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char |
| aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() ); |
| } |
| else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars |
| aSourceClass!=TypeClass_CHAR) |
| { |
| sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range |
| aRet.setValue( &cRet, ::getCharCppuType() ); |
| } |
| break; |
| } |
| case TypeClass_BYTE: |
| aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) ); |
| break; |
| |
| // --- to SHORT, UNSIGNED SHORT ------------------------------------------------------------- |
| case TypeClass_SHORT: |
| aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) ); |
| break; |
| case TypeClass_UNSIGNED_SHORT: |
| aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) ); |
| break; |
| |
| // --- to LONG, UNSIGNED LONG --------------------------------------------------------------- |
| case TypeClass_LONG: |
| aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) ); |
| break; |
| case TypeClass_UNSIGNED_LONG: |
| aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) ); |
| break; |
| |
| // --- to HYPER, UNSIGNED HYPER-------------------------------------------- |
| case TypeClass_HYPER: |
| aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX ); |
| break; |
| case TypeClass_UNSIGNED_HYPER: |
| aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) ); |
| break; |
| |
| // --- to FLOAT, DOUBLE --------------------------------------------------------------------- |
| case TypeClass_FLOAT: |
| aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) ); |
| break; |
| case TypeClass_DOUBLE: |
| aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) ); |
| break; |
| |
| // --- to STRING ---------------------------------------------------------------------------- |
| case TypeClass_STRING: |
| switch (aSourceClass) |
| { |
| case TypeClass_ENUM: |
| { |
| TypeDescription aEnumTD( aSourceType ); |
| aEnumTD.makeComplete(); |
| sal_Int32 nPos; |
| sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue(); |
| for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) |
| { |
| if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos]) |
| break; |
| } |
| if (nPos >= 0) |
| { |
| aRet.setValue( |
| &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos], |
| ::getCppuType( (const OUString *)0 ) ); |
| } |
| else |
| { |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("value is not ENUM!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 ); |
| } |
| break; |
| } |
| |
| case TypeClass_BOOLEAN: |
| aRet <<= OUString::createFromAscii( (*(sal_Bool *)rVal.getValue() ? "true" : "false") ); |
| break; |
| case TypeClass_CHAR: |
| aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 ); |
| break; |
| |
| case TypeClass_BYTE: |
| aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() ); |
| break; |
| case TypeClass_SHORT: |
| aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() ); |
| break; |
| case TypeClass_UNSIGNED_SHORT: |
| aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() ); |
| break; |
| case TypeClass_LONG: |
| aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() ); |
| break; |
| case TypeClass_UNSIGNED_LONG: |
| aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() ); |
| break; |
| case TypeClass_HYPER: |
| aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() ); |
| break; |
| // case TypeClass_UNSIGNED_HYPER: |
| // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() ); |
| // break; |
| // handle unsigned hyper like double |
| |
| default: |
| aRet <<= OUString::valueOf( toDouble( rVal ) ); |
| } |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| |
| if (aRet.hasValue()) |
| return aRet; |
| |
| throw CannotConvertException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ), |
| Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 ); |
| } |
| } |
| |
| namespace stoc_services |
| { |
| //************************************************************************* |
| Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance( |
| const Reference< XComponentContext > & ) |
| throw( RuntimeException ) |
| { |
| static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() ); |
| return s_ref; |
| } |
| } |
| |