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

Generated by: LCOV version 1.11