GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / table / cellvalueconversion.cxx
blob06cb0759ec2427a1a71042dfb5bf85843aa645f9
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 "cellvalueconversion.hxx"
22 #include <com/sun/star/util/NumberFormatter.hpp>
23 #include <com/sun/star/util/NumberFormatsSupplier.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/util/Date.hpp>
26 #include <com/sun/star/util/Time.hpp>
27 #include <com/sun/star/util/DateTime.hpp>
28 #include <com/sun/star/util/XNumberFormatTypes.hpp>
29 #include <com/sun/star/util/NumberFormat.hpp>
30 #include <rtl/strbuf.hxx>
31 #include <rtl/math.hxx>
32 #include <tools/date.hxx>
33 #include <tools/time.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <unotools/syslocale.hxx>
36 #include <comphelper/processfactory.hxx>
38 #include <boost/shared_ptr.hpp>
39 #include <boost/unordered_map.hpp>
41 //......................................................................................................................
42 namespace svt
44 //......................................................................................................................
46 using namespace ::com::sun::star::uno;
47 using ::com::sun::star::util::XNumberFormatter;
48 using ::com::sun::star::util::XNumberFormatter2;
49 using ::com::sun::star::util::NumberFormatter;
50 using ::com::sun::star::util::XNumberFormatsSupplier;
51 using ::com::sun::star::util::NumberFormatsSupplier;
52 using ::com::sun::star::beans::XPropertySet;
53 using ::com::sun::star::lang::Locale;
54 using ::com::sun::star::util::DateTime;
55 using ::com::sun::star::util::XNumberFormatTypes;
57 namespace NumberFormat = ::com::sun::star::util::NumberFormat;
59 typedef ::com::sun::star::util::Time UnoTime;
60 typedef ::com::sun::star::util::Date UnoDate;
62 //==================================================================================================================
63 //= helper
64 //==================================================================================================================
65 namespace
67 //--------------------------------------------------------------------------------------------------------------
68 double lcl_convertDateToDays( long const i_day, long const i_month, long const i_year )
70 long const nNullDateDays = ::Date::DateToDays( 1, 1, 1900 );
71 long const nValueDateDays = ::Date::DateToDays( i_day, i_month, i_year );
73 return nValueDateDays - nNullDateDays;
76 //--------------------------------------------------------------------------------------------------------------
77 double lcl_convertTimeToDays( long const i_hours, long const i_minutes, long const i_seconds, long const i_100thSeconds )
79 return Time( i_hours, i_minutes, i_seconds, i_100thSeconds ).GetTimeInDays();
83 //==================================================================================================================
84 //= IValueNormalization
85 //==================================================================================================================
86 class SAL_NO_VTABLE IValueNormalization
88 public:
89 virtual ~IValueNormalization() { }
91 /** converts the given <code>Any</code> into a <code>double</code> value to be fed into a number formatter
93 virtual double convertToDouble( Any const & i_value ) const = 0;
95 /** returns the format key to be used for formatting values
97 virtual ::sal_Int32 getFormatKey() const = 0;
100 typedef ::boost::shared_ptr< IValueNormalization > PValueNormalization;
101 typedef ::boost::unordered_map< OUString, PValueNormalization, OUStringHash > NormalizerCache;
103 //==================================================================================================================
104 //= CellValueConversion_Data
105 //==================================================================================================================
106 struct CellValueConversion_Data
108 Reference< XNumberFormatter > xNumberFormatter;
109 bool bAttemptedFormatterCreation;
110 NormalizerCache aNormalizers;
112 CellValueConversion_Data()
113 :xNumberFormatter()
114 ,bAttemptedFormatterCreation( false )
115 ,aNormalizers()
120 //==================================================================================================================
121 //= StandardFormatNormalizer
122 //==================================================================================================================
123 class StandardFormatNormalizer : public IValueNormalization
125 protected:
126 StandardFormatNormalizer( Reference< XNumberFormatter > const & i_formatter, ::sal_Int32 const i_numberFormatType )
127 :m_nFormatKey( 0 )
131 ENSURE_OR_THROW( i_formatter.is(), "StandardFormatNormalizer: no formatter!" );
132 Reference< XNumberFormatsSupplier > const xSupplier( i_formatter->getNumberFormatsSupplier(), UNO_SET_THROW );
133 Reference< XNumberFormatTypes > const xTypes( xSupplier->getNumberFormats(), UNO_QUERY_THROW );
134 m_nFormatKey = xTypes->getStandardFormat( i_numberFormatType, SvtSysLocale().GetLanguageTag().getLocale() );
136 catch( const Exception& )
138 DBG_UNHANDLED_EXCEPTION();
142 virtual ::sal_Int32 getFormatKey() const
144 return m_nFormatKey;
147 private:
148 ::sal_Int32 m_nFormatKey;
151 //==================================================================================================================
152 //= DoubleNormalization
153 //==================================================================================================================
154 class DoubleNormalization : public StandardFormatNormalizer
156 public:
157 DoubleNormalization( Reference< XNumberFormatter > const & i_formatter )
158 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER )
162 virtual double convertToDouble( Any const & i_value ) const
164 double returnValue(0);
165 ::rtl::math::setNan( &returnValue );
166 OSL_VERIFY( i_value >>= returnValue );
167 return returnValue;
170 virtual ~DoubleNormalization() { }
173 //==================================================================================================================
174 //= IntegerNormalization
175 //==================================================================================================================
176 class IntegerNormalization : public StandardFormatNormalizer
178 public:
179 IntegerNormalization( Reference< XNumberFormatter > const & i_formatter )
180 :StandardFormatNormalizer( i_formatter, NumberFormat::NUMBER )
184 virtual ~IntegerNormalization() {}
186 virtual double convertToDouble( Any const & i_value ) const
188 sal_Int64 value( 0 );
189 OSL_VERIFY( i_value >>= value );
190 return value;
194 //==================================================================================================================
195 //= BooleanNormalization
196 //==================================================================================================================
197 class BooleanNormalization : public StandardFormatNormalizer
199 public:
200 BooleanNormalization( Reference< XNumberFormatter > const & i_formatter )
201 :StandardFormatNormalizer( i_formatter, NumberFormat::LOGICAL )
205 virtual ~BooleanNormalization() {}
207 virtual double convertToDouble( Any const & i_value ) const
209 bool value( false );
210 OSL_VERIFY( i_value >>= value );
211 return value ? 1 : 0;
215 //==================================================================================================================
216 //= DateTimeNormalization
217 //==================================================================================================================
218 class DateTimeNormalization : public StandardFormatNormalizer
220 public:
221 DateTimeNormalization( Reference< XNumberFormatter > const & i_formatter )
222 :StandardFormatNormalizer( i_formatter, NumberFormat::DATETIME )
226 virtual ~DateTimeNormalization() {}
228 virtual double convertToDouble( Any const & i_value ) const
230 double returnValue(0);
231 ::rtl::math::setNan( &returnValue );
233 // extract actual UNO value
234 DateTime aDateTimeValue;
235 ENSURE_OR_RETURN( i_value >>= aDateTimeValue, "allowed for DateTime values only", returnValue );
237 // date part
238 returnValue = lcl_convertDateToDays( aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year );
240 // time part
241 returnValue += lcl_convertTimeToDays(
242 aDateTimeValue.Hours, aDateTimeValue.Minutes, aDateTimeValue.Seconds, aDateTimeValue.NanoSeconds );
244 // done
245 return returnValue;
249 //==================================================================================================================
250 //= DateNormalization
251 //==================================================================================================================
252 class DateNormalization : public StandardFormatNormalizer
254 public:
255 DateNormalization( Reference< XNumberFormatter > const & i_formatter )
256 :StandardFormatNormalizer( i_formatter, NumberFormat::DATE )
260 virtual ~DateNormalization() {}
262 virtual double convertToDouble( Any const & i_value ) const
264 double returnValue(0);
265 ::rtl::math::setNan( &returnValue );
267 // extract
268 UnoDate aDateValue;
269 ENSURE_OR_RETURN( i_value >>= aDateValue, "allowed for Date values only", returnValue );
271 // convert
272 returnValue = lcl_convertDateToDays( aDateValue.Day, aDateValue.Month, aDateValue.Year );
274 // done
275 return returnValue;
279 //==================================================================================================================
280 //= TimeNormalization
281 //==================================================================================================================
282 class TimeNormalization : public StandardFormatNormalizer
284 public:
285 TimeNormalization( Reference< XNumberFormatter > const & i_formatter )
286 :StandardFormatNormalizer( i_formatter, NumberFormat::TIME )
290 virtual ~TimeNormalization() {}
292 virtual double convertToDouble( Any const & i_value ) const
294 double returnValue(0);
295 ::rtl::math::setNan( &returnValue );
297 // extract
298 UnoTime aTimeValue;
299 ENSURE_OR_RETURN( i_value >>= aTimeValue, "allowed for Time values only", returnValue );
301 // convert
302 returnValue += lcl_convertTimeToDays(
303 aTimeValue.Hours, aTimeValue.Minutes, aTimeValue.Seconds, aTimeValue.NanoSeconds );
305 // done
306 return returnValue;
310 //==================================================================================================================
311 //= operations
312 //==================================================================================================================
313 namespace
315 //--------------------------------------------------------------------------------------------------------------
316 bool lcl_ensureNumberFormatter( CellValueConversion_Data & io_data )
318 if ( io_data.bAttemptedFormatterCreation )
319 return io_data.xNumberFormatter.is();
320 io_data.bAttemptedFormatterCreation = true;
324 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
325 // a number formatter
326 Reference< XNumberFormatter > const xFormatter( NumberFormatter::create( xContext ), UNO_QUERY_THROW );
328 // a supplier of number formats
329 Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale();
331 Reference< XNumberFormatsSupplier > const xSupplier =
332 NumberFormatsSupplier::createWithLocale( xContext, aLocale );
334 // ensure a NullDate we will assume later on
335 UnoDate const aNullDate( 1, 1, 1900 );
336 Reference< XPropertySet > const xFormatSettings( xSupplier->getNumberFormatSettings(), UNO_SET_THROW );
337 xFormatSettings->setPropertyValue( "NullDate", makeAny( aNullDate ) );
339 // knit
340 xFormatter->attachNumberFormatsSupplier( xSupplier );
342 // done
343 io_data.xNumberFormatter = xFormatter;
345 catch( const Exception& )
347 DBG_UNHANDLED_EXCEPTION();
350 return io_data.xNumberFormatter.is();
353 //--------------------------------------------------------------------------------------------------------------
354 bool lcl_getValueNormalizer( CellValueConversion_Data & io_data, Type const & i_valueType,
355 PValueNormalization & o_formatter )
357 NormalizerCache::const_iterator pos = io_data.aNormalizers.find( i_valueType.getTypeName() );
358 if ( pos == io_data.aNormalizers.end() )
360 // never encountered this type before
361 o_formatter.reset();
363 OUString const sTypeName( i_valueType.getTypeName() );
364 TypeClass const eTypeClass = i_valueType.getTypeClass();
366 if ( sTypeName.equals( ::cppu::UnoType< DateTime >::get().getTypeName() ) )
368 o_formatter.reset( new DateTimeNormalization( io_data.xNumberFormatter ) );
370 else if ( sTypeName.equals( ::cppu::UnoType< UnoDate >::get().getTypeName() ) )
372 o_formatter.reset( new DateNormalization( io_data.xNumberFormatter ) );
374 else if ( sTypeName.equals( ::cppu::UnoType< UnoTime >::get().getTypeName() ) )
376 o_formatter.reset( new TimeNormalization( io_data.xNumberFormatter ) );
378 else if ( sTypeName.equals( ::cppu::UnoType< ::sal_Bool >::get().getTypeName() ) )
380 o_formatter.reset( new BooleanNormalization( io_data.xNumberFormatter ) );
382 else if ( sTypeName.equals( ::cppu::UnoType< double >::get().getTypeName() )
383 || sTypeName.equals( ::cppu::UnoType< float >::get().getTypeName() )
386 o_formatter.reset( new DoubleNormalization( io_data.xNumberFormatter ) );
388 else if ( ( eTypeClass == TypeClass_BYTE )
389 || ( eTypeClass == TypeClass_SHORT )
390 || ( eTypeClass == TypeClass_UNSIGNED_SHORT )
391 || ( eTypeClass == TypeClass_LONG )
392 || ( eTypeClass == TypeClass_UNSIGNED_LONG )
393 || ( eTypeClass == TypeClass_HYPER )
396 o_formatter.reset( new IntegerNormalization( io_data.xNumberFormatter ) );
398 else
400 SAL_WARN( "svtools.table", "unsupported type '" << sTypeName << "'!" );
402 io_data.aNormalizers[ sTypeName ] = o_formatter;
404 else
405 o_formatter = pos->second;
407 return !!o_formatter;
411 //==================================================================================================================
412 //= CellValueConversion
413 //==================================================================================================================
414 //------------------------------------------------------------------------------------------------------------------
415 CellValueConversion::CellValueConversion()
416 :m_pData( new CellValueConversion_Data )
420 //------------------------------------------------------------------------------------------------------------------
421 CellValueConversion::~CellValueConversion()
425 //------------------------------------------------------------------------------------------------------------------
426 OUString CellValueConversion::convertToString( const Any& i_value )
428 OUString sStringValue;
429 if ( !i_value.hasValue() )
430 return sStringValue;
432 if ( ! ( i_value >>= sStringValue ) )
434 if ( lcl_ensureNumberFormatter( *m_pData ) )
436 PValueNormalization pNormalizer;
437 if ( lcl_getValueNormalizer( *m_pData, i_value.getValueType(), pNormalizer ) )
441 double const formatterCompliantValue = pNormalizer->convertToDouble( i_value );
442 sal_Int32 const formatKey = pNormalizer->getFormatKey();
443 sStringValue = m_pData->xNumberFormatter->convertNumberToString(
444 formatKey, formatterCompliantValue );
446 catch( const Exception& )
448 DBG_UNHANDLED_EXCEPTION();
454 return sStringValue;
457 //......................................................................................................................
458 } // namespace svt
459 //......................................................................................................................
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */