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