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