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