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