LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/stoc/source/typeconv - convert.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 104 354 29.4 %
Date: 2013-07-09 Functions: 10 17 58.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include <osl/diagnose.h>
      22             : #include <cppuhelper/factory.hxx>
      23             : #include <cppuhelper/implementationentry.hxx>
      24             : #include <cppuhelper/implbase2.hxx>
      25             : 
      26             : #include <typelib/typedescription.hxx>
      27             : #include <uno/data.h>
      28             : 
      29             : #ifdef WNT
      30             : #include <cmath>
      31             : #else
      32             : #include <math.h>
      33             : #endif
      34             : #include <float.h>
      35             : 
      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>
      42             : 
      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"
      51             : 
      52             : namespace stoc_services
      53             : {
      54          26 : Sequence< OUString > tcv_getSupportedServiceNames()
      55             : {
      56          26 :     Sequence< OUString > seqNames(1);
      57          26 :     seqNames.getArray()[0] = OUString(SERVICENAME);
      58          26 :     return seqNames;
      59             : }
      60             : 
      61         153 : OUString tcv_getImplementationName()
      62             : {
      63         153 :     return OUString(IMPLNAME);
      64             : }
      65             : }
      66             : 
      67             : namespace stoc_tcv
      68             : {
      69             : 
      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);
      76             : 
      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);
      80             : 
      81             : static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW(())
      82             : {
      83             :     sal_uInt64 n2 = (n / 3);
      84             :     n -= (2 * n2);
      85             :     return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n);
      86             : }
      87             : #else
      88             : static const double DOUBLE_SAL_UINT64_MAX =
      89             :     (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff);
      90             : 
      91           0 : static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW(())
      92             : {
      93           0 :     return (double)n;
      94             : }
      95             : #endif
      96             : 
      97             : 
      98             : //--------------------------------------------------------------------------------------------------
      99           0 : static inline double round( double aVal )
     100             : {
     101           0 :     sal_Bool bPos   = (aVal >= 0.0);    //
     102           0 :     aVal            = ::fabs( aVal );
     103           0 :     double aUpper   = ::ceil( aVal );
     104             : 
     105           0 :     aVal            = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
     106           0 :     return (bPos ? aVal : -aVal);
     107             : }
     108             : 
     109             : //--------------------------------------------------------------------------------------------------
     110           0 : static sal_Bool getNumericValue( double & rfVal, const OUString & rStr )
     111             : {
     112           0 :     double fRet = rStr.toDouble();
     113           0 :     if (fRet == 0.0)
     114             :     {
     115           0 :         sal_Int32 nLen = rStr.getLength();
     116           0 :         if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
     117             :         {
     118           0 :             rfVal = 0.0;
     119           0 :             return sal_True;
     120             :         }
     121             : 
     122           0 :         OUString trim( rStr.trim() );
     123             : 
     124             :         // try hex
     125           0 :         sal_Int32 nX = trim.indexOf( 'x' );
     126           0 :         if (nX < 0)
     127           0 :             nX = trim.indexOf( 'X' );
     128             : 
     129           0 :         if (nX > 0 && trim[nX-1] == '0') // 0x
     130             :         {
     131           0 :             sal_Bool bNeg = sal_False;
     132           0 :             switch (nX)
     133             :             {
     134             :             case 2: // (+|-)0x...
     135           0 :                 if (trim[0] == '-')
     136           0 :                     bNeg = sal_True;
     137           0 :                 else if (trim[0] != '+')
     138           0 :                     return sal_False;
     139             :             case 1: // 0x...
     140           0 :                 break;
     141             :             default:
     142           0 :                 return sal_False;
     143             :             }
     144             : 
     145           0 :             OUString aHexRest( trim.copy( nX+1 ) );
     146           0 :             sal_uInt64 nRet = aHexRest.toUInt64( 16 );
     147             : 
     148           0 :             if (nRet == 0)
     149             :             {
     150           0 :                 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
     151             :                 {
     152           0 :                     if (aHexRest[nPos] != '0')
     153           0 :                         return sal_False;
     154             :                 }
     155             :             }
     156             : 
     157           0 :             rfVal = (bNeg ? -(double)nRet : (double)nRet);
     158           0 :             return sal_True;
     159             :         }
     160             : 
     161           0 :         nLen = trim.getLength();
     162           0 :         sal_Int32 nPos = 0;
     163             : 
     164             :         // skip +/-
     165           0 :         if (nLen && (trim[0] == '-' || trim[0] == '+'))
     166           0 :             ++nPos;
     167             : 
     168           0 :         while (nPos < nLen) // skip leading zeros
     169             :         {
     170           0 :             if (trim[nPos] != '0')
     171             :             {
     172           0 :                 if (trim[nPos] != '.')
     173           0 :                     return sal_False;
     174           0 :                 ++nPos;
     175           0 :                 while (nPos < nLen) // skip trailing zeros
     176             :                 {
     177           0 :                     if (trim[nPos] != '0')
     178           0 :                         return sal_False;
     179           0 :                     ++nPos;
     180             :                 }
     181           0 :                 break;
     182             :             }
     183           0 :             ++nPos;
     184           0 :         }
     185             :     }
     186           0 :     rfVal = fRet;
     187           0 :     return sal_True;
     188             : }
     189             : 
     190             : //==================================================================================================
     191           0 : static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
     192             : {
     193           0 :     sal_Int32 nLen = rStr.getLength();
     194           0 :     if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
     195             :     {
     196           0 :         rnVal = 0;
     197           0 :         return sal_True;
     198             :     }
     199             : 
     200           0 :     OUString trim( rStr.trim() );
     201             : 
     202             :     // try hex
     203           0 :     sal_Int32 nX = trim.indexOf( 'x' );
     204           0 :     if (nX < 0)
     205           0 :         nX = trim.indexOf( 'X' );
     206             : 
     207           0 :     if (nX >= 0)
     208             :     {
     209           0 :         if (nX > 0 && trim[nX-1] == '0') // 0x
     210             :         {
     211           0 :             sal_Bool bNeg = sal_False;
     212           0 :             switch (nX)
     213             :             {
     214             :             case 2: // (+|-)0x...
     215           0 :                 if (trim[0] == '-')
     216           0 :                     bNeg = sal_True;
     217           0 :                 else if (trim[0] != '+')
     218           0 :                     return sal_False;
     219             :             case 1: // 0x...
     220           0 :                 break;
     221             :             default:
     222           0 :                 return sal_False;
     223             :             }
     224             : 
     225           0 :             OUString aHexRest( trim.copy( nX+1 ) );
     226           0 :             sal_uInt64 nRet = aHexRest.toUInt64( 16 );
     227             : 
     228           0 :             if (nRet == 0)
     229             :             {
     230           0 :                 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
     231             :                 {
     232           0 :                     if (aHexRest[nPos] != '0')
     233           0 :                         return sal_False;
     234             :                 }
     235             :             }
     236             : 
     237           0 :             rnVal = (bNeg ? -static_cast<sal_Int64>(nRet) : nRet);
     238           0 :             return sal_True;
     239             :         }
     240           0 :         return sal_False;
     241             :     }
     242             : 
     243             :     double fVal;
     244           0 :     if (getNumericValue( fVal, rStr ) &&
     245           0 :         fVal >= (double)SAL_INT64_MIN &&
     246           0 :         fVal <= DOUBLE_SAL_UINT64_MAX)
     247             :     {
     248           0 :         rnVal = (sal_Int64)round( fVal );
     249           0 :         return sal_True;
     250             :     }
     251           0 :     return sal_False;
     252             : }
     253             : 
     254             : //==================================================================================================
     255             : class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo >
     256             : {
     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 );
     263             : 
     264             : public:
     265             :     TypeConverter_Impl();
     266             :     virtual ~TypeConverter_Impl();
     267             : 
     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 );
     274             : 
     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);
     280             : };
     281             : 
     282          26 : TypeConverter_Impl::TypeConverter_Impl() {}
     283             : 
     284          38 : TypeConverter_Impl::~TypeConverter_Impl() {}
     285             : 
     286             : // XServiceInfo
     287           0 : OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException )
     288             : {
     289           0 :     return stoc_services::tcv_getImplementationName();
     290             : }
     291             : 
     292             : // XServiceInfo
     293           0 : sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException )
     294             : {
     295           0 :     Sequence< OUString > aSNL = getSupportedServiceNames();
     296           0 :     const OUString * pArray = aSNL.getConstArray();
     297           0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
     298           0 :         if( pArray[i] == ServiceName )
     299           0 :             return sal_True;
     300           0 :     return sal_False;
     301             : }
     302             : 
     303             : // XServiceInfo
     304           0 : Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException )
     305             : {
     306           0 :     return stoc_services::tcv_getSupportedServiceNames();
     307             : }
     308             : 
     309             : //--------------------------------------------------------------------------------------------------
     310          14 : sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
     311             :     throw( CannotConvertException )
     312             : {
     313             :     sal_Int64 nRet;
     314          14 :     TypeClass aDestinationClass = rAny.getValueTypeClass();
     315             : 
     316          14 :     switch (aDestinationClass)
     317             :     {
     318             :     // ENUM
     319             :     case TypeClass_ENUM:
     320           0 :         nRet = *(sal_Int32 *)rAny.getValue();
     321           0 :         break;
     322             :     // BOOL
     323             :     case TypeClass_BOOLEAN:
     324           0 :         nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0);
     325           0 :         break;
     326             :     // CHAR, BYTE
     327             :     case TypeClass_CHAR:
     328           0 :         nRet = *(sal_Unicode *)rAny.getValue();
     329           0 :         break;
     330             :     case TypeClass_BYTE:
     331          13 :         nRet = *(sal_Int8 *)rAny.getValue();
     332          13 :         break;
     333             :     // SHORT
     334             :     case TypeClass_SHORT:
     335           0 :         nRet = *(sal_Int16 *)rAny.getValue();
     336           0 :         break;
     337             :     // UNSIGNED SHORT
     338             :     case TypeClass_UNSIGNED_SHORT:
     339           0 :         nRet = *(sal_uInt16 *)rAny.getValue();
     340           0 :         break;
     341             :     // LONG
     342             :     case TypeClass_LONG:
     343           0 :         nRet = *(sal_Int32 *)rAny.getValue();
     344           0 :         break;
     345             :     // UNSIGNED LONG
     346             :     case TypeClass_UNSIGNED_LONG:
     347           0 :         nRet = *(sal_uInt32 *)rAny.getValue();
     348           0 :         break;
     349             :     // HYPER
     350             :     case TypeClass_HYPER:
     351           0 :         nRet = *(sal_Int64 *)rAny.getValue();
     352           0 :         break;
     353             :     // UNSIGNED HYPER
     354             :     case TypeClass_UNSIGNED_HYPER:
     355             :     {
     356           0 :         nRet = *(sal_Int64 *)rAny.getValue();
     357           0 :         if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound
     358           0 :             (sal_uInt64)nRet <= max)                            // upper bound
     359             :         {
     360           0 :             return nRet;
     361             :         }
     362             :         throw CannotConvertException(
     363             :             OUString("UNSIGNED HYPER out of range!"),
     364           0 :             Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     365             :     }
     366             : 
     367             :     // FLOAT, DOUBLE
     368             :     case TypeClass_FLOAT:
     369             :     {
     370           0 :         double fVal = round( *(float *)rAny.getValue() );
     371           0 :         nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
     372           0 :         if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
     373             :         {
     374           0 :             return nRet;
     375             :         }
     376             :         throw CannotConvertException(
     377             :             OUString("FLOAT out of range!"),
     378           0 :             Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     379             :     }
     380             :     case TypeClass_DOUBLE:
     381             :     {
     382           0 :         double fVal = round( *(double *)rAny.getValue() );
     383           0 :         nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
     384           0 :         if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
     385             :         {
     386           0 :             return nRet;
     387             :         }
     388             :         throw CannotConvertException(
     389             :             OUString("DOUBLE out of range!"),
     390           0 :             Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     391             :     }
     392             : 
     393             :     // STRING
     394             :     case TypeClass_STRING:
     395             :     {
     396           0 :         sal_Int64 fVal = SAL_CONST_INT64(0);
     397           0 :         if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() ))
     398             :         {
     399             :             throw CannotConvertException(
     400             :                 OUString("invalid STRING value!"),
     401           0 :                 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
     402             :         }
     403           0 :         nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal);
     404           0 :         if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max))
     405           0 :             return nRet;
     406             :         throw CannotConvertException(
     407             :             OUString("STRING value out of range!"),
     408           0 :             Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     409             :     }
     410             : 
     411             :     default:
     412             :         throw CannotConvertException(
     413             :             OUString("TYPE is not supported!"),
     414           1 :             Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
     415             :     }
     416             : 
     417          13 :     if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max))
     418          13 :         return nRet;
     419             :     throw CannotConvertException(
     420             :         OUString("VALUE is out of range!"),
     421           0 :         Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     422             : }
     423             : 
     424             : //--------------------------------------------------------------------------------------------------
     425           1 : double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
     426             :     throw( CannotConvertException )
     427             : {
     428             :     double fRet;
     429           1 :     TypeClass aDestinationClass = rAny.getValueTypeClass();
     430             : 
     431           1 :     switch (aDestinationClass)
     432             :     {
     433             :     // ENUM
     434             :     case TypeClass_ENUM:
     435           0 :         fRet = *(sal_Int32 *)rAny.getValue();
     436           0 :         break;
     437             :     // BOOL
     438             :     case TypeClass_BOOLEAN:
     439           0 :         fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0);
     440           0 :         break;
     441             :     // CHAR, BYTE
     442             :     case TypeClass_CHAR:
     443           0 :         fRet = *(sal_Unicode *)rAny.getValue();
     444           0 :         break;
     445             :     case TypeClass_BYTE:
     446           0 :         fRet = *(sal_Int8 *)rAny.getValue();
     447           0 :         break;
     448             :     // SHORT
     449             :     case TypeClass_SHORT:
     450           0 :         fRet = *(sal_Int16 *)rAny.getValue();
     451           0 :         break;
     452             :     // UNSIGNED SHORT
     453             :     case TypeClass_UNSIGNED_SHORT:
     454           0 :         fRet = *(sal_uInt16 *)rAny.getValue();
     455           0 :         break;
     456             :     // LONG
     457             :     case TypeClass_LONG:
     458           0 :         fRet = *(sal_Int32 *)rAny.getValue();
     459           0 :         break;
     460             :     // UNSIGNED LONG
     461             :     case TypeClass_UNSIGNED_LONG:
     462           0 :         fRet = *(sal_uInt32 *)rAny.getValue();
     463           0 :         break;
     464             :     // HYPER
     465             :     case TypeClass_HYPER:
     466           0 :         fRet = (double)*(sal_Int64 *)rAny.getValue();
     467           0 :         break;
     468             :     // UNSIGNED HYPER
     469             :     case TypeClass_UNSIGNED_HYPER:
     470           0 :         fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() );
     471           0 :         break;
     472             :     // FLOAT, DOUBLE
     473             :     case TypeClass_FLOAT:
     474           0 :         fRet = *(float *)rAny.getValue();
     475           0 :         break;
     476             :     case TypeClass_DOUBLE:
     477           1 :         fRet = *(double *)rAny.getValue();
     478           1 :         break;
     479             : 
     480             :     // STRING
     481             :     case TypeClass_STRING:
     482             :     {
     483           0 :         if (! getNumericValue( fRet, *(OUString *)rAny.getValue() ))
     484             :         {
     485             :             throw CannotConvertException(
     486             :                 OUString("invalid STRING value!"),
     487           0 :                 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
     488             :         }
     489           0 :         break;
     490             :     }
     491             : 
     492             :     default:
     493             :         throw CannotConvertException(
     494             :             OUString("TYPE is not supported!"),
     495           0 :             Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
     496             :     }
     497             : 
     498           1 :     if (fRet >= min && fRet <= max)
     499           2 :         return fRet;
     500             :     throw CannotConvertException(
     501             :         OUString("VALUE is out of range!"),
     502           0 :         Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
     503             : }
     504             : 
     505             : //--------------------------------------------------------------------------------------------------
     506         121 : Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
     507             :     throw( IllegalArgumentException, CannotConvertException, RuntimeException)
     508             : {
     509         121 :     Type aSourceType = rVal.getValueType();
     510         121 :     if (aSourceType == aDestType)
     511          17 :         return rVal;
     512             : 
     513         104 :     TypeClass aSourceClass = aSourceType.getTypeClass();
     514         104 :     TypeClass aDestinationClass = aDestType.getTypeClass();
     515             : 
     516         208 :     Any aRet;
     517             : 
     518             :     // convert to...
     519         104 :     switch (aDestinationClass)
     520             :     {
     521             :     // --- to VOID ------------------------------------------------------------------------------
     522             :     case TypeClass_VOID:
     523           0 :         return Any();
     524             :     // --- to ANY -------------------------------------------------------------------------------
     525             :     case TypeClass_ANY:
     526          58 :         return rVal;
     527             : 
     528             :     // --- to STRUCT, UNION, EXCEPTION ----------------------------------------------------------
     529             :     case TypeClass_STRUCT:
     530             : //      case TypeClass_UNION: // xxx todo
     531             :     case TypeClass_EXCEPTION:
     532             :     {
     533             :         // same types or destination type is derived source type?
     534           0 :         TypeDescription aSourceTD( aSourceType );
     535           0 :         TypeDescription aDestTD( aDestType );
     536           0 :         if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
     537             :         {
     538           0 :             aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
     539             :         }
     540             :         else
     541             :         {
     542             :             throw CannotConvertException(
     543             :                 OUString("value is not of same or derived type!"),
     544             :                 Reference< XInterface >(), aDestinationClass,
     545           0 :                 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
     546             :         }
     547           0 :         break;
     548             :     }
     549             :     // --- to INTERFACE -------------------------------------------------------------------------
     550             :     case TypeClass_INTERFACE:
     551             :     {
     552           6 :         if (! rVal.hasValue())
     553             :         {
     554             :             // void -> interface (null)
     555           0 :             void * null_ref = 0;
     556           0 :             aRet.setValue( &null_ref, aDestType );
     557           0 :             break;
     558             :         }
     559             : 
     560          12 :         if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
     561           6 :             !*(XInterface * const *)rVal.getValue())
     562             :         {
     563             :             throw CannotConvertException(
     564             :                 OUString("value is no interface!"),
     565           0 :                 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
     566             :         }
     567          18 :         if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
     568          12 :                    aDestType )).hasValue())
     569             :         {
     570             :             throw CannotConvertException(
     571             :                 OUString("value has no such interface!"),
     572           0 :                 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
     573             :         }
     574           6 :         break;
     575             :     }
     576             :     // --- to SEQUENCE --------------------------------------------------------------------------
     577             :     case TypeClass_SEQUENCE:
     578             :     {
     579          26 :         if (aSourceClass==TypeClass_SEQUENCE)
     580             :         {
     581          26 :             if( aSourceType == aDestType )
     582           0 :                 return rVal;
     583             : 
     584          26 :             TypeDescription aSourceTD( aSourceType );
     585          52 :             TypeDescription aDestTD( aDestType );
     586          26 :             typelib_TypeDescription * pSourceElementTD = 0;
     587             :             TYPELIB_DANGER_GET(
     588             :                 &pSourceElementTD,
     589          26 :                 ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
     590          26 :             typelib_TypeDescription * pDestElementTD = 0;
     591             :             TYPELIB_DANGER_GET(
     592             :                 &pDestElementTD,
     593          26 :                 ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
     594             : 
     595          26 :             sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
     596          26 :             uno_Sequence * pRet = 0;
     597             :             uno_sequence_construct(
     598             :                 &pRet, aDestTD.get(), 0, nPos,
     599          26 :                 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
     600          26 :             aRet.setValue( &pRet, aDestTD.get() );
     601             :             uno_destructData(
     602             :                 &pRet, aDestTD.get(),
     603          26 :                 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
     604             :                 // decr ref count
     605             : 
     606          26 :             char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
     607             :             const char * pSourceElements =
     608          26 :                 (*(const uno_Sequence * const *)rVal.getValue())->elements;
     609             : 
     610         134 :             while (nPos--)
     611             :             {
     612          82 :                 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
     613          82 :                 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
     614             : 
     615             :                 Any aElement(
     616          82 :                     convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
     617             : 
     618          82 :                 if (!uno_assignData(
     619             :                         pDestPos, pDestElementTD,
     620          82 :                         (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         164 :                         reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
     628             :                 {
     629             :                     OSL_ASSERT( false );
     630             :                 }
     631          82 :             }
     632          26 :             TYPELIB_DANGER_RELEASE( pDestElementTD );
     633          52 :             TYPELIB_DANGER_RELEASE( pSourceElementTD );
     634             :         }
     635          26 :         break;
     636             :     }
     637             :     // --- to ENUM ------------------------------------------------------------------------------
     638             :     case TypeClass_ENUM:
     639             :     {
     640          13 :         TypeDescription aEnumTD( aDestType );
     641          13 :         aEnumTD.makeComplete();
     642          13 :         sal_Int32 nPos = -1;
     643             : 
     644          13 :         if (aSourceClass==TypeClass_STRING)
     645             :         {
     646           0 :             for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
     647             :             {
     648           0 :                 if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase(
     649           0 :                         ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] ))
     650           0 :                     break;
     651             :             }
     652             :         }
     653          13 :         else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
     654          13 :                  aSourceClass!=TypeClass_BOOLEAN &&
     655             :                  aSourceClass!=TypeClass_CHAR)
     656             :         {
     657          13 :             sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff );
     658          52 :             for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
     659             :             {
     660          39 :                 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
     661          13 :                     break;
     662             :             }
     663             :         }
     664             : 
     665          13 :         if (nPos >= 0)
     666             :         {
     667             :             aRet.setValue(
     668          13 :                 &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos],
     669          26 :                 aEnumTD.get() );
     670             :         }
     671             :         else
     672             :         {
     673             :             throw CannotConvertException(
     674             :                 OUString("value cannot be converted to demanded ENUM!"),
     675           0 :                 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
     676             :         }
     677          13 :         break;
     678             :     }
     679             : 
     680             :     default:
     681             :         // else simple type conversion possible?
     682             :         try
     683             :         {
     684           1 :             aRet = convertToSimpleType( rVal, aDestinationClass );
     685             :         }
     686           0 :         catch (IllegalArgumentException &)
     687             :         {
     688             :             // ...FailReason::INVALID is thrown
     689             :         }
     690             :     }
     691             : 
     692          45 :     if (aRet.hasValue())
     693          45 :         return aRet;
     694             : 
     695             :     throw CannotConvertException(
     696             :         OUString("conversion not possible!"),
     697         121 :         Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
     698             : }
     699             : 
     700             : //--------------------------------------------------------------------------------------------------
     701           7 : Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
     702             :     throw( IllegalArgumentException, CannotConvertException, RuntimeException )
     703             : {
     704           7 :     switch (aDestinationClass)
     705             :     {
     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           0 :             Reference< XInterface >(), (sal_Int16) 1 );
     721             :     default:
     722           7 :         break;
     723             :     }
     724             : 
     725           7 :     Type aSourceType = rVal.getValueType();
     726           7 :     TypeClass aSourceClass = aSourceType.getTypeClass();
     727           7 :     if (aDestinationClass == aSourceClass)
     728           1 :         return rVal;
     729             : 
     730          12 :     Any aRet;
     731             : 
     732             :     // Convert to...
     733           6 :     switch (aDestinationClass)
     734             :     {
     735             :     // --- to VOID ------------------------------------------------------------------------------
     736             :     case TypeClass_VOID:
     737           0 :         return Any();
     738             : 
     739             :     // --- to ANY -------------------------------------------------------------------------------
     740             :     case TypeClass_ANY:
     741           0 :         return rVal;
     742             : 
     743             :     // --- to BOOL ------------------------------------------------------------------------------
     744             :     case TypeClass_BOOLEAN:
     745           0 :         switch (aSourceClass)
     746             :         {
     747             :         default:
     748             :         {
     749           0 :             sal_Bool bTmp = (toDouble( rVal ) != 0.0);
     750           0 :             aRet.setValue( &bTmp, getBooleanCppuType() );
     751             :         }
     752             :         case TypeClass_ENUM:  // exclude enums
     753           0 :             break;
     754             : 
     755             :         case TypeClass_STRING:
     756             :         {
     757           0 :             const OUString & aStr = *(const OUString *)rVal.getValue();
     758           0 :             if ( aStr == "0" || aStr.equalsIgnoreAsciiCase( OUString("false") ))
     759             :             {
     760           0 :                 sal_Bool bFalse = sal_False;
     761           0 :                 aRet.setValue( &bFalse, getCppuBooleanType() );
     762             :             }
     763           0 :             else if ( aStr == "1" || aStr.equalsIgnoreAsciiCase( OUString("true") ))
     764             :             {
     765           0 :                 sal_Bool bTrue = sal_True;
     766           0 :                 aRet.setValue( &bTrue, getCppuBooleanType() );
     767             :             }
     768             :             else
     769             :             {
     770             :                 throw CannotConvertException(
     771             :                     OUString("STRING has no boolean value!"),
     772           0 :                     Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
     773             :             }
     774             :         }
     775             :         }
     776           0 :         break;
     777             : 
     778             :     // --- to CHAR, BYTE ------------------------------------------------------------------------
     779             :     case TypeClass_CHAR:
     780             :     {
     781           0 :         if (aSourceClass==TypeClass_STRING)
     782             :         {
     783           0 :             if ((*(const OUString *)rVal.getValue()).getLength() == 1)      // single char
     784           0 :                 aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() );
     785             :         }
     786           0 :         else if (aSourceClass!=TypeClass_ENUM &&        // exclude enums, chars
     787             :                  aSourceClass!=TypeClass_CHAR)
     788             :         {
     789           0 :              sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff );    // range
     790           0 :             aRet.setValue( &cRet, ::getCharCppuType() );
     791             :         }
     792           0 :         break;
     793             :     }
     794             :     case TypeClass_BYTE:
     795           0 :         aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) );
     796           0 :         break;
     797             : 
     798             :     // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
     799             :     case TypeClass_SHORT:
     800           0 :         aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) );
     801           0 :         break;
     802             :     case TypeClass_UNSIGNED_SHORT:
     803           0 :         aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) );
     804           0 :         break;
     805             : 
     806             :     // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
     807             :     case TypeClass_LONG:
     808           1 :         aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) );
     809           0 :         break;
     810             :     case TypeClass_UNSIGNED_LONG:
     811           0 :         aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) );
     812           0 :         break;
     813             : 
     814             :     // --- to HYPER, UNSIGNED HYPER--------------------------------------------
     815             :     case TypeClass_HYPER:
     816           0 :         aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
     817           0 :         break;
     818             :     case TypeClass_UNSIGNED_HYPER:
     819           0 :         aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) );
     820           0 :         break;
     821             : 
     822             :     // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
     823             :     case TypeClass_FLOAT:
     824           0 :         aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
     825           0 :         break;
     826             :     case TypeClass_DOUBLE:
     827           0 :         aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) );
     828           0 :         break;
     829             : 
     830             :     // --- to STRING ----------------------------------------------------------------------------
     831             :     case TypeClass_STRING:
     832           5 :         switch (aSourceClass)
     833             :         {
     834             :         case TypeClass_ENUM:
     835             :         {
     836           0 :             TypeDescription aEnumTD( aSourceType );
     837           0 :             aEnumTD.makeComplete();
     838             :             sal_Int32 nPos;
     839           0 :             sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue();
     840           0 :             for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; )
     841             :             {
     842           0 :                 if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos])
     843           0 :                     break;
     844             :             }
     845           0 :             if (nPos >= 0)
     846             :             {
     847             :                 aRet.setValue(
     848           0 :                     &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos],
     849           0 :                     ::getCppuType( (const OUString *)0 ) );
     850             :             }
     851             :             else
     852             :             {
     853             :                 throw CannotConvertException(
     854             :                     OUString("value is not ENUM!"),
     855           0 :                     Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
     856             :             }
     857           0 :             break;
     858             :         }
     859             : 
     860             :         case TypeClass_BOOLEAN:
     861           8 :             aRet <<= (*(sal_Bool *)rVal.getValue()) ?
     862             :                 OUString("true") :
     863           8 :                 OUString("false");
     864           4 :             break;
     865             :         case TypeClass_CHAR:
     866           0 :             aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 );
     867           0 :             break;
     868             : 
     869             :         case TypeClass_BYTE:
     870           0 :             aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() );
     871           0 :             break;
     872             :         case TypeClass_SHORT:
     873           0 :             aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() );
     874           0 :             break;
     875             :         case TypeClass_UNSIGNED_SHORT:
     876           0 :             aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() );
     877           0 :             break;
     878             :         case TypeClass_LONG:
     879           0 :             aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() );
     880           0 :             break;
     881             :         case TypeClass_UNSIGNED_LONG:
     882           0 :             aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() );
     883           0 :             break;
     884             :         case TypeClass_HYPER:
     885           0 :             aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() );
     886           0 :             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
     891             : 
     892             :         default:
     893           1 :             aRet <<= OUString::valueOf( toDouble( rVal ) );
     894             :         }
     895           5 :         break;
     896             : 
     897             :     default:
     898             :         OSL_ASSERT(false);
     899           0 :         break;
     900             :     }
     901             : 
     902           5 :     if (aRet.hasValue())
     903           5 :         return aRet;
     904             : 
     905             :     throw CannotConvertException(
     906             :         OUString("conversion not possible!"),
     907           7 :         Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
     908             : }
     909             : }
     910             : 
     911             : namespace stoc_services
     912             : {
     913             : //*************************************************************************
     914         410 : Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
     915             :     SAL_UNUSED_PARAMETER const Reference< XComponentContext > & )
     916             :     throw( RuntimeException )
     917             : {
     918         410 :     static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
     919         410 :     return s_ref;
     920             : }
     921             : }
     922             : 
     923             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10