Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / stoc / source / typeconv / convert.cxx
blob919a5edc781855285883f186f68b6e64290578c7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <o3tl/any.hxx>
23 #include <osl/diagnose.h>
24 #include <cppuhelper/factory.hxx>
25 #include <cppuhelper/implementationentry.hxx>
26 #include <cppuhelper/implbase.hxx>
27 #include <cppuhelper/supportsservice.hxx>
29 #include <typelib/typedescription.hxx>
30 #include <uno/data.h>
32 #ifdef _WIN32
33 #include <cmath>
34 #else
35 #include <math.h>
36 #endif
37 #include <float.h>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/script/CannotConvertException.hpp>
42 #include <com/sun/star/script/XTypeConverter.hpp>
43 #include <com/sun/star/script/FailReason.hpp>
44 #include <com/sun/star/container/XSet.hpp>
45 #include <com/sun/star/registry/XRegistryKey.hpp>
46 #include <com/sun/star/uno/XComponentContext.hpp>
48 using namespace css::uno;
49 using namespace css::lang;
50 using namespace css::script;
51 using namespace css::registry;
52 using namespace cppu;
53 using namespace osl;
55 namespace stoc_tcv
58 static const sal_uInt64 SAL_UINT64_MAX =
59 (((sal_uInt64(0xffffffff)) << 32) | sal_uInt64(0xffffffff));
60 static const sal_Int64 SAL_INT64_MAX =
61 sal_Int64(((sal_uInt64(0x7fffffff)) << 32) | sal_uInt64(0xffffffff));
62 static const sal_Int64 SAL_INT64_MIN =
63 sal_Int64((sal_uInt64(0x80000000)) << 32);
65 /* MS Visual C++ no conversion from unsigned __int64 to double */
66 #ifdef _MSC_VER
67 static const double DOUBLE_SAL_UINT64_MAX = (((double(SAL_INT64_MAX)) * 2) + 1);
69 static inline double unsigned_int64_to_double( sal_uInt64 n )
71 sal_uInt64 n2 = (n / 3);
72 n -= (2 * n2);
73 return (static_cast<double>(static_cast<sal_Int64>(n2)) * 2.0) + static_cast<double>(static_cast<sal_Int64>(n));
75 #else
76 static const double DOUBLE_SAL_UINT64_MAX =
77 double(((sal_uInt64(0xffffffff)) << 32) | sal_uInt64(0xffffffff));
79 static inline double unsigned_int64_to_double( sal_uInt64 n )
81 return static_cast<double>(n);
83 #endif
86 static inline double round( double aVal )
88 bool bPos = (aVal >= 0.0);
89 aVal = ::fabs( aVal );
90 double aUpper = ::ceil( aVal );
92 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
93 return (bPos ? aVal : -aVal);
97 static bool getNumericValue( double & rfVal, const OUString & rStr )
99 double fRet = rStr.toDouble();
100 if (fRet == 0.0)
102 sal_Int32 nLen = rStr.getLength();
103 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
105 rfVal = 0.0;
106 return true;
109 OUString trim( rStr.trim() );
111 // try hex
112 sal_Int32 nX = trim.indexOf( 'x' );
113 if (nX < 0)
114 nX = trim.indexOf( 'X' );
116 if (nX > 0 && trim[nX-1] == '0') // 0x
118 bool bNeg = false;
119 switch (nX)
121 case 2: // (+|-)0x...
122 if (trim[0] == '-')
123 bNeg = true;
124 else if (trim[0] != '+')
125 return false;
126 break;
127 case 1: // 0x...
128 break;
129 default:
130 return false;
133 OUString aHexRest( trim.copy( nX+1 ) );
134 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
136 if (nRet == 0)
138 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
140 if (aHexRest[nPos] != '0')
141 return false;
145 rfVal = (bNeg ? -static_cast<double>(nRet) : static_cast<double>(nRet));
146 return true;
149 nLen = trim.getLength();
150 sal_Int32 nPos = 0;
152 // skip +/-
153 if (nLen && (trim[0] == '-' || trim[0] == '+'))
154 ++nPos;
156 while (nPos < nLen) // skip leading zeros
158 if (trim[nPos] != '0')
160 if (trim[nPos] != '.')
161 return false;
162 ++nPos;
163 while (nPos < nLen) // skip trailing zeros
165 if (trim[nPos] != '0')
166 return false;
167 ++nPos;
169 break;
171 ++nPos;
174 rfVal = fRet;
175 return true;
179 static bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
181 sal_Int32 nLen = rStr.getLength();
182 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
184 rnVal = 0;
185 return true;
188 OUString trim( rStr.trim() );
190 // try hex
191 sal_Int32 nX = trim.indexOf( 'x' );
192 if (nX < 0)
193 nX = trim.indexOf( 'X' );
195 if (nX >= 0)
197 if (nX > 0 && trim[nX-1] == '0') // 0x
199 bool bNeg = false;
200 switch (nX)
202 case 2: // (+|-)0x...
203 if (trim[0] == '-')
204 bNeg = true;
205 else if (trim[0] != '+')
206 return false;
207 break;
208 case 1: // 0x...
209 break;
210 default:
211 return false;
214 OUString aHexRest( trim.copy( nX+1 ) );
215 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
217 if (nRet == 0)
219 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
221 if (aHexRest[nPos] != '0')
222 return false;
226 rnVal = (bNeg ? -static_cast<sal_Int64>(nRet) : nRet);
227 return true;
229 return false;
232 double fVal;
233 if (getNumericValue( fVal, rStr ) &&
234 fVal >= double(SAL_INT64_MIN) &&
235 fVal <= DOUBLE_SAL_UINT64_MAX)
237 rnVal = static_cast<sal_Int64>(round( fVal ));
238 return true;
240 return false;
244 class TypeConverter_Impl : public WeakImplHelper< XTypeConverter, XServiceInfo >
246 // ...misc helpers...
247 /// @throws CannotConvertException
248 static sal_Int64 toHyper(
249 const Any& rAny, sal_Int64 min, sal_uInt64 max = SAL_UINT64_MAX );
250 /// @throws CannotConvertException
251 static double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX );
253 public:
254 TypeConverter_Impl();
256 // XServiceInfo
257 virtual OUString SAL_CALL getImplementationName() override;
258 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
259 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
261 // XTypeConverter
262 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType ) override;
263 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType ) override;
266 TypeConverter_Impl::TypeConverter_Impl() {}
268 // XServiceInfo
269 OUString TypeConverter_Impl::getImplementationName()
271 return OUString("com.sun.star.comp.stoc.TypeConverter");
274 // XServiceInfo
275 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName)
277 return cppu::supportsService(this, ServiceName);
280 // XServiceInfo
281 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames()
283 Sequence< OUString > seqNames { "com.sun.star.script.Converter" };
284 return seqNames;
288 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
290 sal_Int64 nRet;
291 TypeClass aDestinationClass = rAny.getValueTypeClass();
293 switch (aDestinationClass)
295 // ENUM
296 case TypeClass_ENUM:
297 nRet = *static_cast<sal_Int32 const *>(rAny.getValue());
298 break;
299 // BOOL
300 case TypeClass_BOOLEAN:
301 nRet = *o3tl::forceAccess<bool>(rAny) ? 1 : 0;
302 break;
303 // CHAR, BYTE
304 case TypeClass_CHAR:
305 nRet = *o3tl::forceAccess<sal_Unicode>(rAny);
306 break;
307 case TypeClass_BYTE:
308 nRet = *o3tl::forceAccess<sal_Int8>(rAny);
309 break;
310 // SHORT
311 case TypeClass_SHORT:
312 nRet = *o3tl::forceAccess<sal_Int16>(rAny);
313 break;
314 // UNSIGNED SHORT
315 case TypeClass_UNSIGNED_SHORT:
316 nRet = *o3tl::forceAccess<sal_uInt16>(rAny);
317 break;
318 // LONG
319 case TypeClass_LONG:
320 nRet = *o3tl::forceAccess<sal_Int32>(rAny);
321 break;
322 // UNSIGNED LONG
323 case TypeClass_UNSIGNED_LONG:
324 nRet = *o3tl::forceAccess<sal_uInt32>(rAny);
325 break;
326 // HYPER
327 case TypeClass_HYPER:
328 nRet = *o3tl::forceAccess<sal_Int64>(rAny);
329 break;
330 // UNSIGNED HYPER
331 case TypeClass_UNSIGNED_HYPER:
333 nRet = static_cast<sal_Int64>(*o3tl::forceAccess<sal_uInt64>(rAny));
334 if ((min < 0 || static_cast<sal_uInt64>(nRet) >= static_cast<sal_uInt64>(min)) && // lower bound
335 static_cast<sal_uInt64>(nRet) <= max) // upper bound
337 return nRet;
339 throw CannotConvertException(
340 "UNSIGNED HYPER out of range!",
341 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
344 // FLOAT, DOUBLE
345 case TypeClass_FLOAT:
347 double fVal = round( *o3tl::forceAccess<float>(rAny) );
348 nRet = (fVal > SAL_INT64_MAX ? static_cast<sal_Int64>(static_cast<sal_uInt64>(fVal)) : static_cast<sal_Int64>(fVal));
349 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
351 return nRet;
353 throw CannotConvertException(
354 "FLOAT out of range!",
355 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
357 case TypeClass_DOUBLE:
359 double fVal = round( *o3tl::forceAccess<double>(rAny) );
360 nRet = (fVal > SAL_INT64_MAX ? static_cast<sal_Int64>(static_cast<sal_uInt64>(fVal)) : static_cast<sal_Int64>(fVal));
361 if (fVal >= min && fVal <= unsigned_int64_to_double( max ))
363 return nRet;
365 throw CannotConvertException(
366 "DOUBLE out of range!",
367 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
370 // STRING
371 case TypeClass_STRING:
373 sal_Int64 nVal = SAL_CONST_INT64(0);
374 if (! getHyperValue( nVal, *o3tl::forceAccess<OUString>(rAny) ))
376 throw CannotConvertException(
377 "invalid STRING value!",
378 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
380 nRet = nVal;
381 if (nVal >= min && (nVal < 0 || static_cast<sal_uInt64>(nVal) <= max))
382 return nRet;
383 throw CannotConvertException(
384 "STRING value out of range!",
385 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
388 default:
389 throw CannotConvertException(
390 "TYPE is not supported!",
391 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
394 if (nRet >= min && (nRet < 0 || static_cast<sal_uInt64>(nRet) <= max))
395 return nRet;
396 throw CannotConvertException(
397 "VALUE is out of range!",
398 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
402 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max )
404 double fRet;
405 TypeClass aDestinationClass = rAny.getValueTypeClass();
407 switch (aDestinationClass)
409 // ENUM
410 case TypeClass_ENUM:
411 fRet = *static_cast<sal_Int32 const *>(rAny.getValue());
412 break;
413 // BOOL
414 case TypeClass_BOOLEAN:
415 fRet = *o3tl::forceAccess<bool>(rAny) ? 1.0 : 0.0;
416 break;
417 // CHAR, BYTE
418 case TypeClass_CHAR:
419 fRet = *o3tl::forceAccess<sal_Unicode>(rAny);
420 break;
421 case TypeClass_BYTE:
422 fRet = *o3tl::forceAccess<sal_Int8>(rAny);
423 break;
424 // SHORT
425 case TypeClass_SHORT:
426 fRet = *o3tl::forceAccess<sal_Int16>(rAny);
427 break;
428 // UNSIGNED SHORT
429 case TypeClass_UNSIGNED_SHORT:
430 fRet = *o3tl::forceAccess<sal_uInt16>(rAny);
431 break;
432 // LONG
433 case TypeClass_LONG:
434 fRet = *o3tl::forceAccess<sal_Int32>(rAny);
435 break;
436 // UNSIGNED LONG
437 case TypeClass_UNSIGNED_LONG:
438 fRet = *o3tl::forceAccess<sal_uInt32>(rAny);
439 break;
440 // HYPER
441 case TypeClass_HYPER:
442 fRet = static_cast<double>(*o3tl::forceAccess<sal_Int64>(rAny));
443 break;
444 // UNSIGNED HYPER
445 case TypeClass_UNSIGNED_HYPER:
446 fRet = unsigned_int64_to_double( *o3tl::forceAccess<sal_uInt64>(rAny) );
447 break;
448 // FLOAT, DOUBLE
449 case TypeClass_FLOAT:
450 fRet = *o3tl::forceAccess<float>(rAny);
451 break;
452 case TypeClass_DOUBLE:
453 fRet = *o3tl::forceAccess<double>(rAny);
454 break;
456 // STRING
457 case TypeClass_STRING:
459 if (! getNumericValue( fRet, *o3tl::forceAccess<OUString>(rAny) ))
461 throw CannotConvertException(
462 "invalid STRING value!",
463 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
465 break;
468 default:
469 throw CannotConvertException(
470 "TYPE is not supported!",
471 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
474 if (fRet >= min && fRet <= max)
475 return fRet;
476 throw CannotConvertException(
477 "VALUE is out of range!",
478 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
482 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
484 const Type& aSourceType = rVal.getValueType();
485 if (aSourceType == aDestType)
486 return rVal;
488 TypeClass aSourceClass = aSourceType.getTypeClass();
489 TypeClass aDestinationClass = aDestType.getTypeClass();
491 Any aRet;
493 // convert to...
494 switch (aDestinationClass)
496 // --- to VOID ------------------------------------------------------------------------------
497 case TypeClass_VOID:
498 return Any();
499 // --- to ANY -------------------------------------------------------------------------------
500 case TypeClass_ANY:
501 return rVal;
503 // --- to STRUCT, EXCEPTION ----------------------------------------------------------
504 case TypeClass_STRUCT:
505 case TypeClass_EXCEPTION:
507 // same types or destination type is derived source type?
508 TypeDescription aSourceTD( aSourceType );
509 TypeDescription aDestTD( aDestType );
510 if (!typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
512 throw CannotConvertException(
513 "value is not of same or derived type!",
514 Reference< XInterface >(), aDestinationClass,
515 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
517 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
518 break;
520 // --- to INTERFACE -------------------------------------------------------------------------
521 case TypeClass_INTERFACE:
523 if (! rVal.hasValue())
525 // void -> interface (null)
526 void * null_ref = nullptr;
527 aRet.setValue( &null_ref, aDestType );
528 break;
531 auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>(
532 rVal);
533 if (!ifc || !ifc->is())
535 throw CannotConvertException(
536 "value is not interface",
537 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
539 if (! (aRet = (*ifc)->queryInterface(aDestType )).hasValue())
541 throw CannotConvertException(
542 "value does not implement " + aDestType.getTypeName(),
543 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
545 break;
547 // --- to SEQUENCE --------------------------------------------------------------------------
548 case TypeClass_SEQUENCE:
550 if (aSourceClass==TypeClass_SEQUENCE)
552 if( aSourceType == aDestType )
553 return rVal;
555 TypeDescription aSourceTD( aSourceType );
556 TypeDescription aDestTD( aDestType );
557 typelib_TypeDescription * pSourceElementTD = nullptr;
558 TYPELIB_DANGER_GET(
559 &pSourceElementTD,
560 reinterpret_cast<typelib_IndirectTypeDescription *>(aSourceTD.get())->pType );
561 typelib_TypeDescription * pDestElementTD = nullptr;
562 TYPELIB_DANGER_GET(
563 &pDestElementTD,
564 reinterpret_cast<typelib_IndirectTypeDescription *>(aDestTD.get())->pType );
566 sal_uInt32 nPos = (*static_cast<const uno_Sequence * const *>(rVal.getValue()))->nElements;
567 uno_Sequence * pRet = nullptr;
568 uno_sequence_construct(
569 &pRet, aDestTD.get(), nullptr, nPos,
570 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
571 aRet.setValue( &pRet, aDestTD.get() );
572 uno_destructData(
573 &pRet, aDestTD.get(),
574 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
575 // decr ref count
577 char * pDestElements = (*static_cast<uno_Sequence * const *>(aRet.getValue()))->elements;
578 const char * pSourceElements =
579 (*static_cast<const uno_Sequence * const *>(rVal.getValue()))->elements;
581 while (nPos--)
583 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
584 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
586 Any aElement(
587 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
589 if (!uno_assignData(
590 pDestPos, pDestElementTD,
591 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
592 ? &aElement
593 : const_cast< void * >( aElement.getValue() )),
594 pDestElementTD,
595 reinterpret_cast< uno_QueryInterfaceFunc >(
596 cpp_queryInterface),
597 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
598 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
600 OSL_ASSERT( false );
603 TYPELIB_DANGER_RELEASE( pDestElementTD );
604 TYPELIB_DANGER_RELEASE( pSourceElementTD );
606 break;
608 // --- to ENUM ------------------------------------------------------------------------------
609 case TypeClass_ENUM:
611 TypeDescription aEnumTD( aDestType );
612 aEnumTD.makeComplete();
613 sal_Int32 nPos = -1;
615 if (aSourceClass==TypeClass_STRING)
617 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
619 if (o3tl::forceAccess<OUString>(rVal)->equalsIgnoreAsciiCase(
620 reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->ppEnumNames[nPos] ))
621 break;
624 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
625 aSourceClass!=TypeClass_BOOLEAN &&
626 aSourceClass!=TypeClass_CHAR)
628 sal_Int32 nEnumValue = static_cast<sal_Int32>(toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ));
629 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
631 if (nEnumValue == reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos])
632 break;
636 if (nPos < 0)
638 throw CannotConvertException(
639 "value cannot be converted to demanded ENUM!",
640 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
643 aRet.setValue(
644 &reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos],
645 aEnumTD.get() );
647 break;
650 default:
651 // else simple type conversion possible?
654 aRet = convertToSimpleType( rVal, aDestinationClass );
656 catch (IllegalArgumentException &)
658 // ...FailReason::INVALID is thrown
662 if (aRet.hasValue())
663 return aRet;
665 throw CannotConvertException(
666 "conversion not possible!",
667 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
671 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
673 switch (aDestinationClass)
675 // only simple Conversion of _simple_ types
676 case TypeClass_VOID:
677 case TypeClass_BOOLEAN:
678 case TypeClass_BYTE:
679 case TypeClass_SHORT:
680 case TypeClass_UNSIGNED_SHORT:
681 case TypeClass_LONG:
682 case TypeClass_UNSIGNED_LONG:
683 case TypeClass_HYPER:
684 case TypeClass_UNSIGNED_HYPER:
685 case TypeClass_FLOAT:
686 case TypeClass_DOUBLE:
687 case TypeClass_CHAR:
688 case TypeClass_STRING:
689 case TypeClass_ANY:
690 break;
692 default:
693 throw IllegalArgumentException(
694 "destination type is not simple!",
695 Reference< XInterface >(), sal_Int16(1) );
698 const Type& aSourceType = rVal.getValueType();
699 TypeClass aSourceClass = aSourceType.getTypeClass();
700 if (aDestinationClass == aSourceClass)
701 return rVal;
703 Any aRet;
705 // Convert to...
706 switch (aDestinationClass)
708 // --- to VOID ------------------------------------------------------------------------------
709 case TypeClass_VOID:
710 return Any();
712 // --- to ANY -------------------------------------------------------------------------------
713 case TypeClass_ANY:
714 return rVal;
716 // --- to BOOL ------------------------------------------------------------------------------
717 case TypeClass_BOOLEAN:
718 switch (aSourceClass)
720 default:
721 aRet <<= (toDouble( rVal ) != 0.0);
722 break;
723 case TypeClass_ENUM: // exclude enums
724 break;
726 case TypeClass_STRING:
728 const OUString & aStr = *o3tl::forceAccess<OUString>(rVal);
729 if ( aStr == "0" || aStr.equalsIgnoreAsciiCase( "false" ))
731 aRet <<= false;
733 else if ( aStr == "1" || aStr.equalsIgnoreAsciiCase( "true" ))
735 aRet <<= true;
737 else
739 throw CannotConvertException(
740 "STRING has no boolean value, " + aStr,
741 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
745 break;
747 // --- to CHAR, BYTE ------------------------------------------------------------------------
748 case TypeClass_CHAR:
750 if (aSourceClass==TypeClass_STRING)
752 auto const s = o3tl::forceAccess<OUString>(rVal);
753 if (s->getLength() == 1) // single char
754 aRet <<= (*s)[0];
756 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
757 aSourceClass!=TypeClass_CHAR)
759 aRet <<= sal_Unicode(toHyper( rVal, 0, 0xffff )); // range
761 break;
763 case TypeClass_BYTE:
764 aRet <<= static_cast<sal_Int8>( toHyper( rVal, -sal_Int64(0x80), 0x7f ) );
765 break;
767 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
768 case TypeClass_SHORT:
769 aRet <<= static_cast<sal_Int16>( toHyper( rVal, -sal_Int64(0x8000), 0x7fff ) );
770 break;
771 case TypeClass_UNSIGNED_SHORT:
772 aRet <<= static_cast<sal_uInt16>( toHyper( rVal, 0, 0xffff ) );
773 break;
775 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
776 case TypeClass_LONG:
777 aRet <<= static_cast<sal_Int32>( toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ) );
778 break;
779 case TypeClass_UNSIGNED_LONG:
780 aRet <<= static_cast<sal_uInt32>( toHyper( rVal, 0, 0xffffffff ) );
781 break;
783 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
784 case TypeClass_HYPER:
785 aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX );
786 break;
787 case TypeClass_UNSIGNED_HYPER:
788 aRet <<= static_cast<sal_uInt64>( toHyper( rVal, 0 ) );
789 break;
791 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
792 case TypeClass_FLOAT:
793 aRet <<= static_cast<float>( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
794 break;
795 case TypeClass_DOUBLE:
796 aRet <<= toDouble( rVal, -DBL_MAX, DBL_MAX );
797 break;
799 // --- to STRING ----------------------------------------------------------------------------
800 case TypeClass_STRING:
801 switch (aSourceClass)
803 case TypeClass_ENUM:
805 TypeDescription aEnumTD( aSourceType );
806 aEnumTD.makeComplete();
807 sal_Int32 nPos;
808 sal_Int32 nEnumValue = *static_cast<sal_Int32 const *>(rVal.getValue());
809 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
811 if (nEnumValue == reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos])
812 break;
814 if (nPos < 0)
816 throw CannotConvertException(
817 "value is not ENUM!",
818 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
821 aRet <<= OUString::unacquired(
822 &reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->ppEnumNames[nPos]);
824 break;
827 case TypeClass_BOOLEAN:
828 aRet <<= *o3tl::forceAccess<bool>(rVal) ?
829 OUString("true") :
830 OUString("false");
831 break;
832 case TypeClass_CHAR:
833 aRet <<= OUString(*o3tl::forceAccess<sal_Unicode>(rVal));
834 break;
836 case TypeClass_BYTE:
837 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int8>(rVal) );
838 break;
839 case TypeClass_SHORT:
840 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int16>(rVal) );
841 break;
842 case TypeClass_UNSIGNED_SHORT:
843 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt16>(rVal) );
844 break;
845 case TypeClass_LONG:
846 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int32>(rVal) );
847 break;
848 case TypeClass_UNSIGNED_LONG:
849 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt32>(rVal) );
850 break;
851 case TypeClass_HYPER:
852 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int64>(rVal) );
853 break;
854 // case TypeClass_UNSIGNED_HYPER:
855 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
856 // break;
857 // handle unsigned hyper like double
859 default:
860 aRet <<= OUString::number( toDouble( rVal ) );
862 break;
864 default:
865 OSL_ASSERT(false);
866 break;
869 if (aRet.hasValue())
870 return aRet;
872 throw CannotConvertException(
873 "conversion not possible!",
874 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
879 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
880 com_sun_star_comp_stoc_TypeConverter_get_implementation(css::uno::XComponentContext*,
881 css::uno::Sequence<css::uno::Any> const &)
883 return ::cppu::acquire(new stoc_tcv::TypeConverter_Impl());
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */