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 9 : Sequence< OUString > tcv_getSupportedServiceNames()
59 : {
60 9 : Sequence< OUString > seqNames(1);
61 9 : seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
62 9 : return seqNames;
63 : }
64 :
65 28 : OUString tcv_getImplementationName()
66 : {
67 28 : 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 9 : TypeConverter_Impl::TypeConverter_Impl()
287 : {
288 9 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
289 9 : }
290 :
291 21 : TypeConverter_Impl::~TypeConverter_Impl()
292 : {
293 7 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
294 14 : }
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 0 : double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const
436 : throw( CannotConvertException )
437 : {
438 : double fRet;
439 0 : TypeClass aDestinationClass = rAny.getValueTypeClass();
440 :
441 0 : 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 0 : fRet = *(sal_Int8 *)rAny.getValue();
457 0 : 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 0 : if (fRet >= min && fRet <= max)
509 0 : 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 0 : Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
517 : throw( IllegalArgumentException, CannotConvertException, RuntimeException)
518 : {
519 0 : Type aSourceType = rVal.getValueType();
520 0 : if (aSourceType == aDestType)
521 0 : return rVal;
522 :
523 0 : TypeClass aSourceClass = aSourceType.getTypeClass();
524 0 : TypeClass aDestinationClass = aDestType.getTypeClass();
525 :
526 0 : Any aRet;
527 :
528 : // convert to...
529 0 : 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 0 : 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 0 : if (rVal.getValueTypeClass() != TypeClass_INTERFACE ||
571 0 : !*(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 0 : if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface(
578 0 : 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 0 : break;
585 : }
586 : // --- to SEQUENCE --------------------------------------------------------------------------
587 : case TypeClass_SEQUENCE:
588 : {
589 0 : if (aSourceClass==TypeClass_SEQUENCE)
590 : {
591 0 : if( aSourceType == aDestType )
592 0 : return rVal;
593 :
594 0 : TypeDescription aSourceTD( aSourceType );
595 0 : TypeDescription aDestTD( aDestType );
596 0 : typelib_TypeDescription * pSourceElementTD = 0;
597 0 : TYPELIB_DANGER_GET(
598 : &pSourceElementTD,
599 : ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType );
600 0 : typelib_TypeDescription * pDestElementTD = 0;
601 0 : TYPELIB_DANGER_GET(
602 : &pDestElementTD,
603 : ((typelib_IndirectTypeDescription *)aDestTD.get())->pType );
604 :
605 0 : sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements;
606 0 : uno_Sequence * pRet = 0;
607 : uno_sequence_construct(
608 : &pRet, aDestTD.get(), 0, nPos,
609 0 : reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
610 0 : aRet.setValue( &pRet, aDestTD.get() );
611 : uno_destructData(
612 : &pRet, aDestTD.get(),
613 0 : reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
614 : // decr ref count
615 :
616 0 : char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements;
617 : const char * pSourceElements =
618 0 : (*(const uno_Sequence * const *)rVal.getValue())->elements;
619 :
620 0 : while (nPos--)
621 : {
622 0 : char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
623 0 : const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
624 :
625 : Any aElement(
626 0 : convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
627 :
628 0 : 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 0 : reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
638 : {
639 : OSL_ASSERT( false );
640 : }
641 0 : }
642 0 : TYPELIB_DANGER_RELEASE( pDestElementTD );
643 0 : TYPELIB_DANGER_RELEASE( pSourceElementTD );
644 : }
645 0 : 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 0 : aRet = convertToSimpleType( rVal, aDestinationClass );
696 : }
697 0 : catch (IllegalArgumentException &)
698 : {
699 : // ...FailReason::INVALID is thrown
700 : }
701 : }
702 :
703 0 : if (aRet.hasValue())
704 0 : return aRet;
705 :
706 : throw CannotConvertException(
707 : OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
708 0 : Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
709 : }
710 :
711 : //--------------------------------------------------------------------------------------------------
712 0 : Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
713 : throw( IllegalArgumentException, CannotConvertException, RuntimeException )
714 : {
715 0 : 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 0 : break;
734 : }
735 :
736 0 : Type aSourceType = rVal.getValueType();
737 0 : TypeClass aSourceClass = aSourceType.getTypeClass();
738 0 : if (aDestinationClass == aSourceClass)
739 0 : return rVal;
740 :
741 0 : Any aRet;
742 :
743 : // Convert to...
744 0 : 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 0 : switch (aSourceClass)
757 : {
758 : default:
759 : {
760 0 : sal_Bool bTmp = (toDouble( rVal ) != 0.0);
761 0 : aRet.setValue( &bTmp, getBooleanCppuType() );
762 : }
763 : case TypeClass_ENUM: // exclude enums
764 0 : 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 0 : 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 0 : if (aRet.hasValue())
914 0 : return aRet;
915 :
916 : throw CannotConvertException(
917 : OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ),
918 0 : Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
919 : }
920 : }
921 :
922 : namespace stoc_services
923 : {
924 : //*************************************************************************
925 71 : Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance(
926 : SAL_UNUSED_PARAMETER const Reference< XComponentContext > & )
927 : throw( RuntimeException )
928 : {
929 71 : static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() );
930 71 : return s_ref;
931 : }
932 : }
933 :
934 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|