summaryrefslogtreecommitdiff
path: root/stoc/source/typeconv/convert.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'stoc/source/typeconv/convert.cxx')
-rw-r--r--stoc/source/typeconv/convert.cxx966
1 files changed, 966 insertions, 0 deletions
diff --git a/stoc/source/typeconv/convert.cxx b/stoc/source/typeconv/convert.cxx
new file mode 100644
index 000000000000..9fef114f33fd
--- /dev/null
+++ b/stoc/source/typeconv/convert.cxx
@@ -0,0 +1,966 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: convert.cxx,v $
+ * $Revision: 1.18 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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;
+}
+}
+