nss: upgrade to release 3.73
[LibreOffice.git] / stoc / source / typeconv / convert.cxx
blobe8fe65830a992e5d8342982cf21c91d502865de7
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 <o3tl/safeint.hxx>
24 #include <osl/diagnose.h>
25 #include <cppuhelper/implbase.hxx>
26 #include <cppuhelper/supportsservice.hxx>
28 #include <typelib/typedescription.hxx>
29 #include <uno/data.h>
31 #ifdef _WIN32
32 #include <cmath>
33 #else
34 #include <math.h>
35 #endif
36 #include <float.h>
38 #include <com/sun/star/lang/IllegalArgumentException.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/script/CannotConvertException.hpp>
41 #include <com/sun/star/script/XTypeConverter.hpp>
42 #include <com/sun/star/script/FailReason.hpp>
44 namespace com::sun::star::uno { class XComponentContext; }
46 using namespace css::uno;
47 using namespace css::lang;
48 using namespace css::script;
49 using namespace cppu;
50 using namespace osl;
52 namespace stoc_tcv
55 static double round( double aVal )
57 bool bPos = (aVal >= 0.0);
58 aVal = ::fabs( aVal );
59 double aUpper = ::ceil( aVal );
61 aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0);
62 return (bPos ? aVal : -aVal);
66 static bool getNumericValue( double & rfVal, const OUString & rStr )
68 double fRet = rStr.toDouble();
69 if (fRet == 0.0)
71 sal_Int32 nLen = rStr.getLength();
72 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
74 rfVal = 0.0;
75 return true;
78 OUString trim( rStr.trim() );
80 // try hex
81 sal_Int32 nX = trim.indexOf( 'x' );
82 if (nX < 0)
83 nX = trim.indexOf( 'X' );
85 if (nX > 0 && trim[nX-1] == '0') // 0x
87 bool bNeg = false;
88 switch (nX)
90 case 2: // (+|-)0x...
91 if (trim[0] == '-')
92 bNeg = true;
93 else if (trim[0] != '+')
94 return false;
95 break;
96 case 1: // 0x...
97 break;
98 default:
99 return false;
102 OUString aHexRest( trim.copy( nX+1 ) );
103 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
105 if (nRet == 0)
107 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
109 if (aHexRest[nPos] != '0')
110 return false;
114 rfVal = (bNeg ? -static_cast<double>(nRet) : static_cast<double>(nRet));
115 return true;
118 nLen = trim.getLength();
119 sal_Int32 nPos = 0;
121 // skip +/-
122 if (nLen && (trim[0] == '-' || trim[0] == '+'))
123 ++nPos;
125 while (nPos < nLen) // skip leading zeros
127 if (trim[nPos] != '0')
129 if (trim[nPos] != '.')
130 return false;
131 ++nPos;
132 while (nPos < nLen) // skip trailing zeros
134 if (trim[nPos] != '0')
135 return false;
136 ++nPos;
138 break;
140 ++nPos;
143 rfVal = fRet;
144 return true;
148 static bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr )
150 sal_Int32 nLen = rStr.getLength();
151 if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case
153 rnVal = 0;
154 return true;
157 OUString trim( rStr.trim() );
159 // try hex
160 sal_Int32 nX = trim.indexOf( 'x' );
161 if (nX < 0)
162 nX = trim.indexOf( 'X' );
164 if (nX >= 0)
166 if (nX > 0 && trim[nX-1] == '0') // 0x
168 bool bNeg = false;
169 switch (nX)
171 case 2: // (+|-)0x...
172 if (trim[0] == '-')
173 bNeg = true;
174 else if (trim[0] != '+')
175 return false;
176 break;
177 case 1: // 0x...
178 break;
179 default:
180 return false;
183 OUString aHexRest( trim.copy( nX+1 ) );
184 sal_uInt64 nRet = aHexRest.toUInt64( 16 );
186 if (nRet == 0)
188 for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; )
190 if (aHexRest[nPos] != '0')
191 return false;
195 rnVal = (bNeg ? -static_cast<sal_Int64>(nRet) : nRet);
196 return true;
198 return false;
201 double fVal;
202 if (getNumericValue( fVal, rStr ) &&
203 fVal >= double(SAL_MIN_INT64) &&
204 fVal <= double(SAL_MAX_UINT64))
206 rnVal = static_cast<sal_Int64>(round( fVal ));
207 return true;
209 return false;
212 namespace {
214 class TypeConverter_Impl : public WeakImplHelper< XTypeConverter, XServiceInfo >
216 // ...misc helpers...
217 /// @throws CannotConvertException
218 static sal_Int64 toHyper(
219 const Any& rAny, sal_Int64 min, sal_uInt64 max = SAL_MAX_UINT64 );
220 /// @throws CannotConvertException
221 static double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX );
223 public:
224 TypeConverter_Impl();
226 // XServiceInfo
227 virtual OUString SAL_CALL getImplementationName() override;
228 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
229 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
231 // XTypeConverter
232 virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType ) override;
233 virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType ) override;
238 TypeConverter_Impl::TypeConverter_Impl() {}
240 // XServiceInfo
241 OUString TypeConverter_Impl::getImplementationName()
243 return "com.sun.star.comp.stoc.TypeConverter";
246 // XServiceInfo
247 sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName)
249 return cppu::supportsService(this, ServiceName);
252 // XServiceInfo
253 Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames()
255 return { "com.sun.star.script.Converter" };
259 sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max )
261 sal_Int64 nRet;
262 TypeClass aDestinationClass = rAny.getValueTypeClass();
264 switch (aDestinationClass)
266 // ENUM
267 case TypeClass_ENUM:
268 nRet = *static_cast<sal_Int32 const *>(rAny.getValue());
269 break;
270 // BOOL
271 case TypeClass_BOOLEAN:
272 nRet = *o3tl::forceAccess<bool>(rAny) ? 1 : 0;
273 break;
274 // CHAR, BYTE
275 case TypeClass_CHAR:
276 nRet = *o3tl::forceAccess<sal_Unicode>(rAny);
277 break;
278 case TypeClass_BYTE:
279 nRet = *o3tl::forceAccess<sal_Int8>(rAny);
280 break;
281 // SHORT
282 case TypeClass_SHORT:
283 nRet = *o3tl::forceAccess<sal_Int16>(rAny);
284 break;
285 // UNSIGNED SHORT
286 case TypeClass_UNSIGNED_SHORT:
287 nRet = *o3tl::forceAccess<sal_uInt16>(rAny);
288 break;
289 // LONG
290 case TypeClass_LONG:
291 nRet = *o3tl::forceAccess<sal_Int32>(rAny);
292 break;
293 // UNSIGNED LONG
294 case TypeClass_UNSIGNED_LONG:
295 nRet = *o3tl::forceAccess<sal_uInt32>(rAny);
296 break;
297 // HYPER
298 case TypeClass_HYPER:
299 nRet = *o3tl::forceAccess<sal_Int64>(rAny);
300 break;
301 // UNSIGNED HYPER
302 case TypeClass_UNSIGNED_HYPER:
304 auto const n = *o3tl::forceAccess<sal_uInt64>(rAny);
305 if ((min < 0 || n >= o3tl::make_unsigned(min)) && // lower bound
306 n <= max) // upper bound
308 return static_cast<sal_Int64>(n);
310 throw CannotConvertException(
311 "UNSIGNED HYPER out of range!",
312 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
315 // FLOAT, DOUBLE
316 case TypeClass_FLOAT:
318 double fVal = round( *o3tl::forceAccess<float>(rAny) );
319 if (fVal >= min && fVal <= max)
321 nRet = (fVal >= 0.0 ? static_cast<sal_Int64>(static_cast<sal_uInt64>(fVal)) : static_cast<sal_Int64>(fVal));
322 return nRet;
324 throw CannotConvertException(
325 "FLOAT out of range!",
326 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
328 case TypeClass_DOUBLE:
330 double fVal = round( *o3tl::forceAccess<double>(rAny) );
331 if (fVal >= min && fVal <= max)
333 nRet = (fVal >= 0.0 ? static_cast<sal_Int64>(static_cast<sal_uInt64>(fVal)) : static_cast<sal_Int64>(fVal));
334 return nRet;
336 throw CannotConvertException(
337 "DOUBLE out of range!",
338 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
341 // STRING
342 case TypeClass_STRING:
344 sal_Int64 nVal = SAL_CONST_INT64(0);
345 if (! getHyperValue( nVal, *o3tl::forceAccess<OUString>(rAny) ))
347 throw CannotConvertException(
348 "invalid STRING value!",
349 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
351 nRet = nVal;
352 if (nVal >= min && (nVal < 0 || o3tl::make_unsigned(nVal) <= max))
353 return nRet;
354 throw CannotConvertException(
355 "STRING value out of range!",
356 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
359 default:
360 throw CannotConvertException(
361 "TYPE is not supported!",
362 Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
365 if (nRet >= min && (nRet < 0 || o3tl::make_unsigned(nRet) <= max))
366 return nRet;
367 throw CannotConvertException(
368 "VALUE is out of range!",
369 Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
373 double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max )
375 double fRet;
376 TypeClass aDestinationClass = rAny.getValueTypeClass();
378 switch (aDestinationClass)
380 // ENUM
381 case TypeClass_ENUM:
382 fRet = *static_cast<sal_Int32 const *>(rAny.getValue());
383 break;
384 // BOOL
385 case TypeClass_BOOLEAN:
386 fRet = *o3tl::forceAccess<bool>(rAny) ? 1.0 : 0.0;
387 break;
388 // CHAR, BYTE
389 case TypeClass_CHAR:
390 fRet = *o3tl::forceAccess<sal_Unicode>(rAny);
391 break;
392 case TypeClass_BYTE:
393 fRet = *o3tl::forceAccess<sal_Int8>(rAny);
394 break;
395 // SHORT
396 case TypeClass_SHORT:
397 fRet = *o3tl::forceAccess<sal_Int16>(rAny);
398 break;
399 // UNSIGNED SHORT
400 case TypeClass_UNSIGNED_SHORT:
401 fRet = *o3tl::forceAccess<sal_uInt16>(rAny);
402 break;
403 // LONG
404 case TypeClass_LONG:
405 fRet = *o3tl::forceAccess<sal_Int32>(rAny);
406 break;
407 // UNSIGNED LONG
408 case TypeClass_UNSIGNED_LONG:
409 fRet = *o3tl::forceAccess<sal_uInt32>(rAny);
410 break;
411 // HYPER
412 case TypeClass_HYPER:
413 fRet = static_cast<double>(*o3tl::forceAccess<sal_Int64>(rAny));
414 break;
415 // UNSIGNED HYPER
416 case TypeClass_UNSIGNED_HYPER:
417 fRet = static_cast<double>(*o3tl::forceAccess<sal_uInt64>(rAny));
418 break;
419 // FLOAT, DOUBLE
420 case TypeClass_FLOAT:
421 fRet = *o3tl::forceAccess<float>(rAny);
422 break;
423 case TypeClass_DOUBLE:
424 fRet = *o3tl::forceAccess<double>(rAny);
425 break;
427 // STRING
428 case TypeClass_STRING:
430 if (! getNumericValue( fRet, *o3tl::forceAccess<OUString>(rAny) ))
432 throw CannotConvertException(
433 "invalid STRING value!",
434 Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 );
436 break;
439 default:
440 throw CannotConvertException(
441 "TYPE is not supported!",
442 Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 );
445 if (fRet >= min && fRet <= max)
446 return fRet;
447 throw CannotConvertException(
448 "VALUE is out of range!",
449 Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 );
453 Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType )
455 const Type& aSourceType = rVal.getValueType();
456 if (aSourceType == aDestType)
457 return rVal;
459 TypeClass aSourceClass = aSourceType.getTypeClass();
460 TypeClass aDestinationClass = aDestType.getTypeClass();
462 Any aRet;
464 // convert to...
465 switch (aDestinationClass)
467 // --- to VOID ------------------------------------------------------------------------------
468 case TypeClass_VOID:
469 return Any();
470 // --- to ANY -------------------------------------------------------------------------------
471 case TypeClass_ANY:
472 return rVal;
474 // --- to STRUCT, EXCEPTION ----------------------------------------------------------
475 case TypeClass_STRUCT:
476 case TypeClass_EXCEPTION:
478 // same types or destination type is derived source type?
479 TypeDescription aSourceTD( aSourceType );
480 TypeDescription aDestTD( aDestType );
481 if (!typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() ))
483 throw CannotConvertException(
484 "value is not of same or derived type!",
485 Reference< XInterface >(), aDestinationClass,
486 FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 );
488 aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT.
489 break;
491 // --- to INTERFACE -------------------------------------------------------------------------
492 case TypeClass_INTERFACE:
494 if (! rVal.hasValue())
496 // void -> interface (null)
497 void * null_ref = nullptr;
498 aRet.setValue( &null_ref, aDestType );
499 break;
502 auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>(
503 rVal);
504 if (!ifc || !ifc->is())
506 throw CannotConvertException(
507 "value is not interface",
508 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
510 aRet = (*ifc)->queryInterface(aDestType );
511 if (! aRet.hasValue())
513 throw CannotConvertException(
514 "value does not implement " + aDestType.getTypeName(),
515 Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 );
517 break;
519 // --- to SEQUENCE --------------------------------------------------------------------------
520 case TypeClass_SEQUENCE:
522 if (aSourceClass==TypeClass_SEQUENCE)
524 if( aSourceType == aDestType )
525 return rVal;
527 TypeDescription aSourceTD( aSourceType );
528 TypeDescription aDestTD( aDestType );
529 typelib_TypeDescription * pSourceElementTD = nullptr;
530 TYPELIB_DANGER_GET(
531 &pSourceElementTD,
532 reinterpret_cast<typelib_IndirectTypeDescription *>(aSourceTD.get())->pType );
533 typelib_TypeDescription * pDestElementTD = nullptr;
534 TYPELIB_DANGER_GET(
535 &pDestElementTD,
536 reinterpret_cast<typelib_IndirectTypeDescription *>(aDestTD.get())->pType );
538 sal_uInt32 nPos = (*static_cast<const uno_Sequence * const *>(rVal.getValue()))->nElements;
539 uno_Sequence * pRet = nullptr;
540 uno_sequence_construct(
541 &pRet, aDestTD.get(), nullptr, nPos,
542 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
543 aRet.setValue( &pRet, aDestTD.get() );
544 uno_destructData(
545 &pRet, aDestTD.get(),
546 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
547 // decr ref count
549 char * pDestElements = (*static_cast<uno_Sequence * const *>(aRet.getValue()))->elements;
550 const char * pSourceElements =
551 (*static_cast<const uno_Sequence * const *>(rVal.getValue()))->elements;
553 while (nPos--)
555 char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize);
556 const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize);
558 Any aElement(
559 convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) );
561 if (!uno_assignData(
562 pDestPos, pDestElementTD,
563 (pDestElementTD->eTypeClass == typelib_TypeClass_ANY
564 ? &aElement
565 : const_cast< void * >( aElement.getValue() )),
566 pDestElementTD,
567 reinterpret_cast< uno_QueryInterfaceFunc >(
568 cpp_queryInterface),
569 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
570 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ))
572 OSL_ASSERT( false );
575 TYPELIB_DANGER_RELEASE( pDestElementTD );
576 TYPELIB_DANGER_RELEASE( pSourceElementTD );
578 break;
580 // --- to ENUM ------------------------------------------------------------------------------
581 case TypeClass_ENUM:
583 TypeDescription aEnumTD( aDestType );
584 aEnumTD.makeComplete();
585 sal_Int32 nPos = -1;
587 if (aSourceClass==TypeClass_STRING)
589 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
591 if (o3tl::forceAccess<OUString>(rVal)->equalsIgnoreAsciiCase(
592 OUString::unacquired(&reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->ppEnumNames[nPos]) ))
593 break;
596 else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper()
597 aSourceClass!=TypeClass_BOOLEAN &&
598 aSourceClass!=TypeClass_CHAR)
600 sal_Int32 nEnumValue = static_cast<sal_Int32>(toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ));
601 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
603 if (nEnumValue == reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos])
604 break;
608 if (nPos < 0)
610 throw CannotConvertException(
611 "value cannot be converted to demanded ENUM!",
612 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
615 aRet.setValue(
616 &reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos],
617 aEnumTD.get() );
619 break;
622 default:
623 // else simple type conversion possible?
626 aRet = convertToSimpleType( rVal, aDestinationClass );
628 catch (IllegalArgumentException &)
630 // ...FailReason::INVALID is thrown
634 if (aRet.hasValue())
635 return aRet;
637 throw CannotConvertException(
638 "conversion not possible!",
639 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
643 Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass )
645 switch (aDestinationClass)
647 // only simple Conversion of _simple_ types
648 case TypeClass_VOID:
649 case TypeClass_BOOLEAN:
650 case TypeClass_BYTE:
651 case TypeClass_SHORT:
652 case TypeClass_UNSIGNED_SHORT:
653 case TypeClass_LONG:
654 case TypeClass_UNSIGNED_LONG:
655 case TypeClass_HYPER:
656 case TypeClass_UNSIGNED_HYPER:
657 case TypeClass_FLOAT:
658 case TypeClass_DOUBLE:
659 case TypeClass_CHAR:
660 case TypeClass_STRING:
661 case TypeClass_ANY:
662 break;
664 default:
665 throw IllegalArgumentException(
666 "destination type is not simple!",
667 Reference< XInterface >(), sal_Int16(1) );
670 const Type& aSourceType = rVal.getValueType();
671 TypeClass aSourceClass = aSourceType.getTypeClass();
672 if (aDestinationClass == aSourceClass)
673 return rVal;
675 Any aRet;
677 // Convert to...
678 switch (aDestinationClass)
680 // --- to VOID ------------------------------------------------------------------------------
681 case TypeClass_VOID:
682 return Any();
684 // --- to ANY -------------------------------------------------------------------------------
685 case TypeClass_ANY:
686 return rVal;
688 // --- to BOOL ------------------------------------------------------------------------------
689 case TypeClass_BOOLEAN:
690 switch (aSourceClass)
692 default:
693 aRet <<= (toDouble( rVal ) != 0.0);
694 break;
695 case TypeClass_ENUM: // exclude enums
696 break;
698 case TypeClass_STRING:
700 const OUString & aStr = *o3tl::forceAccess<OUString>(rVal);
701 if ( aStr == "0" || aStr.equalsIgnoreAsciiCase( "false" ))
703 aRet <<= false;
705 else if ( aStr == "1" || aStr.equalsIgnoreAsciiCase( "true" ))
707 aRet <<= true;
709 else
711 throw CannotConvertException(
712 "STRING has no boolean value, " + aStr,
713 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 );
717 break;
719 // --- to CHAR, BYTE ------------------------------------------------------------------------
720 case TypeClass_CHAR:
722 if (aSourceClass==TypeClass_STRING)
724 auto const s = o3tl::forceAccess<OUString>(rVal);
725 if (s->getLength() == 1) // single char
726 aRet <<= (*s)[0];
728 else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars
729 aSourceClass!=TypeClass_CHAR)
731 aRet <<= sal_Unicode(toHyper( rVal, 0, 0xffff )); // range
733 break;
735 case TypeClass_BYTE:
736 aRet <<= static_cast<sal_Int8>( toHyper( rVal, -sal_Int64(0x80), 0x7f ) );
737 break;
739 // --- to SHORT, UNSIGNED SHORT -------------------------------------------------------------
740 case TypeClass_SHORT:
741 aRet <<= static_cast<sal_Int16>( toHyper( rVal, -sal_Int64(0x8000), 0x7fff ) );
742 break;
743 case TypeClass_UNSIGNED_SHORT:
744 aRet <<= static_cast<sal_uInt16>( toHyper( rVal, 0, 0xffff ) );
745 break;
747 // --- to LONG, UNSIGNED LONG ---------------------------------------------------------------
748 case TypeClass_LONG:
749 aRet <<= static_cast<sal_Int32>( toHyper( rVal, -sal_Int64(0x80000000), 0x7fffffff ) );
750 break;
751 case TypeClass_UNSIGNED_LONG:
752 aRet <<= static_cast<sal_uInt32>( toHyper( rVal, 0, 0xffffffff ) );
753 break;
755 // --- to HYPER, UNSIGNED HYPER--------------------------------------------
756 case TypeClass_HYPER:
757 aRet <<= toHyper( rVal, SAL_MIN_INT64, SAL_MAX_INT64 );
758 break;
759 case TypeClass_UNSIGNED_HYPER:
760 aRet <<= static_cast<sal_uInt64>( toHyper( rVal, 0 ) );
761 break;
763 // --- to FLOAT, DOUBLE ---------------------------------------------------------------------
764 case TypeClass_FLOAT:
765 aRet <<= static_cast<float>( toDouble( rVal, -FLT_MAX, FLT_MAX ) );
766 break;
767 case TypeClass_DOUBLE:
768 aRet <<= toDouble( rVal, -DBL_MAX, DBL_MAX );
769 break;
771 // --- to STRING ----------------------------------------------------------------------------
772 case TypeClass_STRING:
773 switch (aSourceClass)
775 case TypeClass_ENUM:
777 TypeDescription aEnumTD( aSourceType );
778 aEnumTD.makeComplete();
779 sal_Int32 nPos;
780 sal_Int32 nEnumValue = *static_cast<sal_Int32 const *>(rVal.getValue());
781 for ( nPos = reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->nEnumValues; nPos--; )
783 if (nEnumValue == reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->pEnumValues[nPos])
784 break;
786 if (nPos < 0)
788 throw CannotConvertException(
789 "value is not ENUM!",
790 Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 );
793 aRet <<= OUString::unacquired(
794 &reinterpret_cast<typelib_EnumTypeDescription *>(aEnumTD.get())->ppEnumNames[nPos]);
796 break;
799 case TypeClass_BOOLEAN:
800 aRet <<= *o3tl::forceAccess<bool>(rVal) ?
801 OUString("true") :
802 OUString("false");
803 break;
804 case TypeClass_CHAR:
805 aRet <<= OUString(*o3tl::forceAccess<sal_Unicode>(rVal));
806 break;
808 case TypeClass_BYTE:
809 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int8>(rVal) );
810 break;
811 case TypeClass_SHORT:
812 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int16>(rVal) );
813 break;
814 case TypeClass_UNSIGNED_SHORT:
815 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt16>(rVal) );
816 break;
817 case TypeClass_LONG:
818 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int32>(rVal) );
819 break;
820 case TypeClass_UNSIGNED_LONG:
821 aRet <<= OUString::number( *o3tl::forceAccess<sal_uInt32>(rVal) );
822 break;
823 case TypeClass_HYPER:
824 aRet <<= OUString::number( *o3tl::forceAccess<sal_Int64>(rVal) );
825 break;
826 // case TypeClass_UNSIGNED_HYPER:
827 // aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() );
828 // break;
829 // handle unsigned hyper like double
831 default:
832 aRet <<= OUString::number( toDouble( rVal ) );
834 break;
836 default:
837 OSL_ASSERT(false);
838 break;
841 if (aRet.hasValue())
842 return aRet;
844 throw CannotConvertException(
845 "conversion not possible!",
846 Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 );
851 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
852 com_sun_star_comp_stoc_TypeConverter_get_implementation(css::uno::XComponentContext*,
853 css::uno::Sequence<css::uno::Any> const &)
855 return ::cppu::acquire(new stoc_tcv::TypeConverter_Impl());
858 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */