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