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