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