26#include <osl/diagnose.h>
30#include <typelib/typedescription.hxx>
40#include <com/sun/star/lang/IllegalArgumentException.hpp>
41#include <com/sun/star/lang/XServiceInfo.hpp>
42#include <com/sun/star/script/CannotConvertException.hpp>
43#include <com/sun/star/script/XTypeConverter.hpp>
44#include <com/sun/star/script/FailReason.hpp>
48using namespace css::uno;
49using namespace css::lang;
50using namespace css::script;
57static double round(
double aVal )
59 bool bPos = (aVal >= 0.0);
60 aVal = ::fabs( aVal );
61 double aUpper = ::ceil( aVal );
63 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
64 return (bPos ? aVal : -aVal);
73 size_t nLen = rStr.size();
74 if (!nLen || (nLen == 1 && rStr[0] ==
'0'))
83 size_t nX =
trim.find(
'x' );
84 if (nX == std::u16string_view::npos)
85 nX =
trim.find(
'X' );
87 if (nX > 0 && nX != std::u16string_view::npos &&
trim[nX-1] ==
'0')
95 else if (
trim[0] !=
'+')
104 OUString aHexRest(
trim.substr( nX+1 ) );
105 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
109 for ( sal_Int32
nPos = aHexRest.getLength();
nPos--; )
111 if (aHexRest[
nPos] !=
'0')
116 rfVal = (bNeg ? -
static_cast<double>(nRet) :
static_cast<double>(nRet));
124 if (nLen && (
trim[0] ==
'-' ||
trim[0] ==
'+'))
152 size_t nLen = rStr.size();
153 if (!nLen || (nLen == 1 && rStr[0] ==
'0'))
162 size_t nX =
trim.find(
'x' );
163 if (nX == std::u16string_view::npos)
164 nX =
trim.find(
'X' );
166 if (nX != std::u16string_view::npos)
168 if (nX > 0 &&
trim[nX-1] ==
'0')
176 else if (
trim[0] !=
'+')
185 OUString aHexRest(
trim.substr( nX+1 ) );
186 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
190 for ( sal_Int32
nPos = aHexRest.getLength();
nPos--; )
192 if (aHexRest[
nPos] !=
'0')
197 rnVal = (bNeg ? -
static_cast<sal_Int64
>(nRet) : nRet);
208 rnVal =
static_cast<sal_Int64
>(
round( fVal ));
216class TypeConverter_Impl :
public WeakImplHelper< XTypeConverter, XServiceInfo >
220 static sal_Int64 toHyper(
221 const Any& rAny, sal_Int64 min, sal_uInt64 max = SAL_MAX_UINT64 );
223 static double toDouble(
const Any& rAny,
double min = -DBL_MAX,
double max = DBL_MAX );
226 TypeConverter_Impl();
234 virtual Any SAL_CALL convertTo(
const Any& aFrom,
const Type& DestinationType )
override;
235 virtual Any SAL_CALL convertToSimpleType(
const Any& aFrom, TypeClass aDestinationType )
override;
240TypeConverter_Impl::TypeConverter_Impl() {}
243OUString TypeConverter_Impl::getImplementationName()
245 return "com.sun.star.comp.stoc.TypeConverter";
249sal_Bool TypeConverter_Impl::supportsService(
const OUString& ServiceName)
255Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames()
257 return {
"com.sun.star.script.Converter" };
261sal_Int64 TypeConverter_Impl::toHyper(
const Any& rAny, sal_Int64 min, sal_uInt64 max )
264 TypeClass aDestinationClass = rAny.getValueTypeClass();
266 switch (aDestinationClass)
270 nRet = *
static_cast<sal_Int32
const *
>(rAny.getValue());
273 case TypeClass_BOOLEAN:
274 nRet = *o3tl::forceAccess<bool>(rAny) ? 1 : 0;
278 nRet = *o3tl::forceAccess<sal_Unicode>(rAny);
281 nRet = *o3tl::forceAccess<sal_Int8>(rAny);
284 case TypeClass_SHORT:
285 nRet = *o3tl::forceAccess<sal_Int16>(rAny);
288 case TypeClass_UNSIGNED_SHORT:
289 nRet = *o3tl::forceAccess<sal_uInt16>(rAny);
293 nRet = *o3tl::forceAccess<sal_Int32>(rAny);
296 case TypeClass_UNSIGNED_LONG:
297 nRet = *o3tl::forceAccess<sal_uInt32>(rAny);
300 case TypeClass_HYPER:
301 nRet = *o3tl::forceAccess<sal_Int64>(rAny);
304 case TypeClass_UNSIGNED_HYPER:
306 auto const n = *o3tl::forceAccess<sal_uInt64>(rAny);
310 return static_cast<sal_Int64
>(
n);
312 throw CannotConvertException(
313 "UNSIGNED HYPER out of range!",
314 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
318 case TypeClass_FLOAT:
320 double fVal =
round( *o3tl::forceAccess<float>(rAny) );
321 if (fVal >= min && fVal <= max)
323 nRet = (fVal >= 0.0 ?
static_cast<sal_Int64
>(
static_cast<sal_uInt64
>(fVal)) :
static_cast<sal_Int64
>(fVal));
326 throw CannotConvertException(
327 "FLOAT out of range!",
328 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
330 case TypeClass_DOUBLE:
332 double fVal =
round( *o3tl::forceAccess<double>(rAny) );
333 if (fVal >= min && fVal <= max)
335 nRet = (fVal >= 0.0 ?
static_cast<sal_Int64
>(
static_cast<sal_uInt64
>(fVal)) :
static_cast<sal_Int64
>(fVal));
338 throw CannotConvertException(
339 "DOUBLE out of range!",
340 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
344 case TypeClass_STRING:
346 sal_Int64 nVal = SAL_CONST_INT64(0);
347 if (!
getHyperValue( nVal, *o3tl::forceAccess<OUString>(rAny) ))
349 throw CannotConvertException(
350 "invalid STRING value!",
351 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
356 throw CannotConvertException(
357 "STRING value out of range!",
358 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
362 throw CannotConvertException(
364 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
369 throw CannotConvertException(
370 "VALUE is out of range!",
371 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
375double TypeConverter_Impl::toDouble(
const Any& rAny,
double min,
double max )
378 TypeClass aDestinationClass = rAny.getValueTypeClass();
380 switch (aDestinationClass)
384 fRet = *
static_cast<sal_Int32
const *
>(rAny.getValue());
387 case TypeClass_BOOLEAN:
388 fRet = *o3tl::forceAccess<bool>(rAny) ? 1.0 : 0.0;
392 fRet = *o3tl::forceAccess<sal_Unicode>(rAny);
395 fRet = *o3tl::forceAccess<sal_Int8>(rAny);
398 case TypeClass_SHORT:
399 fRet = *o3tl::forceAccess<sal_Int16>(rAny);
402 case TypeClass_UNSIGNED_SHORT:
403 fRet = *o3tl::forceAccess<sal_uInt16>(rAny);
407 fRet = *o3tl::forceAccess<sal_Int32>(rAny);
410 case TypeClass_UNSIGNED_LONG:
411 fRet = *o3tl::forceAccess<sal_uInt32>(rAny);
414 case TypeClass_HYPER:
415 fRet =
static_cast<double>(*o3tl::forceAccess<sal_Int64>(rAny));
418 case TypeClass_UNSIGNED_HYPER:
419 fRet =
static_cast<double>(*o3tl::forceAccess<sal_uInt64>(rAny));
422 case TypeClass_FLOAT:
423 fRet = *o3tl::forceAccess<float>(rAny);
425 case TypeClass_DOUBLE:
426 fRet = *o3tl::forceAccess<double>(rAny);
430 case TypeClass_STRING:
434 throw CannotConvertException(
435 "invalid STRING value!",
436 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
442 throw CannotConvertException(
444 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
447 if (fRet >= min && fRet <= max)
449 throw CannotConvertException(
450 "VALUE is out of range!",
451 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
455Any SAL_CALL TypeConverter_Impl::convertTo(
const Any& rVal,
const Type& aDestType )
457 const Type& aSourceType = rVal.getValueType();
458 if (aSourceType == aDestType)
461 TypeClass aSourceClass = aSourceType.getTypeClass();
462 TypeClass aDestinationClass = aDestType.getTypeClass();
467 switch (aDestinationClass)
477 case TypeClass_STRUCT:
478 case TypeClass_EXCEPTION:
481 TypeDescription aSourceTD( aSourceType );
482 TypeDescription aDestTD( aDestType );
485 throw CannotConvertException(
486 "value is not of same or derived type!",
487 Reference< XInterface >(), aDestinationClass,
488 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
490 aRet.setValue( rVal.getValue(), aDestTD.get() );
494 case TypeClass_INTERFACE:
496 if (! rVal.hasValue())
499 void * null_ref =
nullptr;
501 aRet.setValue( &null_ref, aDestType );
505 auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>(
507 if (!ifc || !ifc->is())
509 throw CannotConvertException(
510 "value is not interface",
511 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
513 aRet = (*ifc)->queryInterface(aDestType );
514 if (! aRet.hasValue())
516 throw CannotConvertException(
517 "value does not implement " + aDestType.getTypeName(),
518 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
523 case TypeClass_SEQUENCE:
525 if (aSourceClass==TypeClass_SEQUENCE)
527 if( aSourceType == aDestType )
530 TypeDescription aSourceTD( aSourceType );
531 TypeDescription aDestTD( aDestType );
539 throw css::lang::IllegalArgumentException(
540 "Bad XTypeConverter::convertTo destination " + aDestType.getTypeName(),
546 reinterpret_cast<typelib_IndirectTypeDescription *
>(aSourceTD.get())->pType );
550 reinterpret_cast<typelib_IndirectTypeDescription *
>(aDestTD.get())->pType );
552 sal_uInt32
nPos = (*
static_cast<const uno_Sequence *
const *
>(rVal.getValue()))->nElements;
553 uno_Sequence * pRet =
nullptr;
555 &pRet, aDestTD.get(),
nullptr, nPos,
556 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire) );
557 aRet.setValue( &pRet, aDestTD.get() );
559 &pRet, aDestTD.get(),
560 reinterpret_cast< uno_ReleaseFunc
>(cpp_release) );
563 char * pDestElements = (*
static_cast<uno_Sequence *
const *
>(aRet.getValue()))->elements;
564 const char * pSourceElements =
565 (*
static_cast<const uno_Sequence *
const *
>(rVal.getValue()))->elements;
569 char * pDestPos = pDestElements + (
nPos * pDestElementTD->nSize);
570 const char * pSourcePos = pSourceElements + (
nPos * pSourceElementTD->nSize);
573 convertTo(
Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
576 pDestPos, pDestElementTD,
577 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
579 :
const_cast< void *
>( aElement.getValue() )),
581 reinterpret_cast< uno_QueryInterfaceFunc
>(
583 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire),
584 reinterpret_cast< uno_ReleaseFunc
>(cpp_release) ))
589 TYPELIB_DANGER_RELEASE( pDestElementTD );
590 TYPELIB_DANGER_RELEASE( pSourceElementTD );
597 TypeDescription aEnumTD( aDestType );
598 aEnumTD.makeComplete();
601 if (aSourceClass==TypeClass_STRING)
603 for ( nPos =
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->nEnumValues; nPos--; )
606 OUString::unacquired(&
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->ppEnumNames[nPos]) ))
610 else if (aSourceClass!=TypeClass_ENUM &&
611 aSourceClass!=TypeClass_BOOLEAN &&
612 aSourceClass!=TypeClass_CHAR)
614 sal_Int32 nEnumValue =
static_cast<sal_Int32
>(toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ));
615 for ( nPos =
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->nEnumValues;
nPos--; )
617 if (nEnumValue ==
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->pEnumValues[
nPos])
624 throw CannotConvertException(
625 "value cannot be converted to demanded ENUM!",
626 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
630 &
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->pEnumValues[nPos],
640 aRet = convertToSimpleType( rVal, aDestinationClass );
642 catch (IllegalArgumentException &)
651 throw CannotConvertException(
652 "conversion not possible!",
653 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
657Any TypeConverter_Impl::convertToSimpleType(
const Any& rVal, TypeClass aDestinationClass )
659 switch (aDestinationClass)
663 case TypeClass_BOOLEAN:
665 case TypeClass_SHORT:
666 case TypeClass_UNSIGNED_SHORT:
668 case TypeClass_UNSIGNED_LONG:
669 case TypeClass_HYPER:
670 case TypeClass_UNSIGNED_HYPER:
671 case TypeClass_FLOAT:
672 case TypeClass_DOUBLE:
674 case TypeClass_STRING:
679 throw IllegalArgumentException(
680 "destination type is not simple!",
681 Reference< XInterface >(), sal_Int16(1) );
684 const Type& aSourceType = rVal.getValueType();
685 TypeClass aSourceClass = aSourceType.getTypeClass();
686 if (aDestinationClass == aSourceClass)
692 switch (aDestinationClass)
703 case TypeClass_BOOLEAN:
704 switch (aSourceClass)
712 case TypeClass_STRING:
714 const OUString &
aStr = *o3tl::forceAccess<OUString>(rVal);
715 if ( aStr ==
"0" ||
aStr.equalsIgnoreAsciiCase(
"false" ))
719 else if ( aStr ==
"1" ||
aStr.equalsIgnoreAsciiCase(
"true" ))
725 throw CannotConvertException(
726 "STRING has no boolean value, " + aStr,
727 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
736 if (aSourceClass==TypeClass_STRING)
738 auto const s = o3tl::forceAccess<OUString>(rVal);
739 if (s->getLength() == 1)
742 else if (aSourceClass!=TypeClass_ENUM &&
743 aSourceClass!=TypeClass_CHAR)
750 aRet <<= static_cast<sal_Int8>( toHyper( rVal, -sal_Int64(0x80), 0x7f ) );
754 case TypeClass_SHORT:
755 aRet <<= static_cast<sal_Int16>( toHyper( rVal, -sal_Int64(0x8000), 0x7fff ) );
757 case TypeClass_UNSIGNED_SHORT:
758 aRet <<= static_cast<sal_uInt16>( toHyper( rVal, 0, 0xffff ) );
763 aRet <<= static_cast<sal_Int32>( toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ) );
765 case TypeClass_UNSIGNED_LONG:
766 aRet <<= static_cast<sal_uInt32>( toHyper( rVal, 0, 0xffffffff ) );
770 case TypeClass_HYPER:
771 aRet <<= toHyper( rVal, SAL_MIN_INT64, SAL_MAX_INT64 );
773 case TypeClass_UNSIGNED_HYPER:
774 aRet <<= static_cast<sal_uInt64>( toHyper( rVal, 0 ) );
778 case TypeClass_FLOAT:
779 aRet <<= static_cast<float>(
toDouble( rVal, -FLT_MAX, FLT_MAX ) );
781 case TypeClass_DOUBLE:
782 aRet <<=
toDouble( rVal, -DBL_MAX, DBL_MAX );
786 case TypeClass_STRING:
787 switch (aSourceClass)
791 TypeDescription aEnumTD( aSourceType );
792 aEnumTD.makeComplete();
794 sal_Int32 nEnumValue = *
static_cast<sal_Int32
const *
>(rVal.getValue());
795 for ( nPos =
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->nEnumValues;
nPos--; )
797 if (nEnumValue ==
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->pEnumValues[
nPos])
802 throw CannotConvertException(
803 "value is not ENUM!",
804 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
807 aRet <<= OUString::unacquired(
808 &
reinterpret_cast<typelib_EnumTypeDescription *
>(aEnumTD.get())->ppEnumNames[nPos]);
813 case TypeClass_BOOLEAN:
814 aRet <<= *o3tl::forceAccess<bool>(rVal) ?
819 aRet <<= OUString(*o3tl::forceAccess<sal_Unicode>(rVal));
823 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int8>(rVal) );
825 case TypeClass_SHORT:
826 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int16>(rVal) );
828 case TypeClass_UNSIGNED_SHORT:
829 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt16>(rVal) );
832 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int32>(rVal) );
834 case TypeClass_UNSIGNED_LONG:
835 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt32>(rVal) );
837 case TypeClass_HYPER:
838 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int64>(rVal) );
846 aRet <<= OUString::number(
toDouble( rVal ) );
858 throw CannotConvertException(
859 "conversion not possible!",
860 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
865extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
867 css::uno::Sequence<css::uno::Any>
const &)
869 return ::cppu::acquire(
new stoc_tcv::TypeConverter_Impl());
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_stoc_TypeConverter_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
sal_Bool SAL_CALL uno_assignData(void *pDest, typelib_TypeDescription *pDestTD, void *pSource, typelib_TypeDescription *pSourceTD, uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
struct _typelib_TypeDescription typelib_TypeDescription
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
double toDouble(std::u16string_view str)
constexpr std::underlying_type_t< T > to_underlying(T e)
static double round(double aVal)
static bool getHyperValue(sal_Int64 &rnVal, std::u16string_view rStr)
static bool getNumericValue(double &rfVal, std::u16string_view rStr)
sal_Bool SAL_CALL uno_sequence_construct(uno_Sequence **ppSequence, typelib_TypeDescription *pTypeDescr, void *pElements, sal_Int32 len, uno_AcquireFunc acquire) SAL_THROW_EXTERN_C()
sal_Bool SAL_CALL typelib_typedescription_isAssignableFrom(typelib_TypeDescription *pAssignable, typelib_TypeDescription *pFrom) SAL_THROW_EXTERN_C()