nss: upgrade to release 3.73
[LibreOffice.git] / forms / source / xforms / convert.cxx
blobd68018f47d221894e2abe989429b9b1d92f62165
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 .
21 #include "convert.hxx"
23 #include <sstream>
24 #include <rtl/math.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <osl/diagnose.h>
27 #include <tools/date.hxx>
28 #include <com/sun/star/uno/Type.hxx>
29 #include <com/sun/star/util/Date.hpp>
30 #include <com/sun/star/util/DateTime.hpp>
31 #include <com/sun/star/util/Time.hpp>
32 #include <comphelper/sequence.hxx>
33 #include <unotools/datetime.hxx>
35 using xforms::Convert;
36 using com::sun::star::uno::Any;
37 using com::sun::star::uno::makeAny;
38 using namespace std;
39 using namespace utl;
41 Convert::Convert()
42 : maMap()
44 init();
47 #define ADD_ENTRY(XCONVERT,TYPE) XCONVERT->maMap[ cppu::UnoType<TYPE>::get() ] = Convert_t( &lcl_toXSD_##TYPE, &lcl_toAny_##TYPE )
49 namespace
52 OUString lcl_toXSD_OUString( const Any& rAny )
53 { OUString sStr; rAny >>= sStr; return sStr; }
56 Any lcl_toAny_OUString( const OUString& rStr )
57 { return Any(rStr); }
60 OUString lcl_toXSD_bool( const Any& rAny )
61 { bool b = false; rAny >>= b; return b ? OUString("true") : OUString("false"); }
64 Any lcl_toAny_bool( const OUString& rStr )
66 bool b = ( rStr == "true" || rStr == "1" );
67 return makeAny( b );
71 OUString lcl_toXSD_double( const Any& rAny )
73 double f = 0.0;
74 rAny >>= f;
76 return std::isfinite( f )
77 ? rtl::math::doubleToUString( f, rtl_math_StringFormat_Automatic,
78 rtl_math_DecimalPlaces_Max, '.',
79 true )
80 : OUString();
84 Any lcl_toAny_double( const OUString& rString )
86 rtl_math_ConversionStatus eStatus;
87 double f = rtl::math::stringToDouble(
88 rString, '.', ',', &eStatus );
89 return ( eStatus == rtl_math_ConversionStatus_Ok ) ? makeAny( f ) : Any();
93 void lcl_appendInt32ToBuffer( const sal_Int32 _nValue, OUStringBuffer& _rBuffer, sal_Int16 _nMinDigits )
95 if ( ( _nMinDigits >= 4 ) && ( _nValue < 1000 ) )
96 _rBuffer.append( '0' );
97 if ( ( _nMinDigits >= 3 ) && ( _nValue < 100 ) )
98 _rBuffer.append( '0' );
99 if ( ( _nMinDigits >= 2 ) && ( _nValue < 10 ) )
100 _rBuffer.append( '0' );
101 _rBuffer.append( _nValue );
105 OUString lcl_toXSD_UNODate_typed( const css::util::Date& rDate )
108 OUStringBuffer sInfo;
109 lcl_appendInt32ToBuffer( rDate.Year, sInfo, 4 );
110 sInfo.append( "-" );
111 lcl_appendInt32ToBuffer( rDate.Month, sInfo, 2 );
112 sInfo.append( "-" );
113 lcl_appendInt32ToBuffer( rDate.Day, sInfo, 2 );
115 return sInfo.makeStringAndClear();
119 OUString lcl_toXSD_UNODate( const Any& rAny )
121 css::util::Date aDate;
122 OSL_VERIFY( rAny >>= aDate );
123 return lcl_toXSD_UNODate_typed( aDate );
127 css::util::Date lcl_toUNODate( const OUString& rString )
129 css::util::Date aDate( 1, 1, 1900 );
131 bool bWellformed = ISO8601parseDate(rString, aDate);
133 // sanity checks
134 if ( ( aDate.Year > 9999 ) || ( aDate.Month < 1 ) || ( aDate.Month > 12 ) || ( aDate.Day < 1 ) || ( aDate.Day > 31 ) )
135 bWellformed = false;
136 else
138 ::Date aDateCheck( 1, aDate.Month, aDate.Year );
139 if ( aDate.Day > aDateCheck.GetDaysInMonth() )
140 bWellformed = false;
143 // all okay?
144 if ( !bWellformed )
145 return css::util::Date( 1, 1, 1900 );
147 return aDate;
151 Any lcl_toAny_UNODate( const OUString& rString )
153 return makeAny( lcl_toUNODate( rString ) );
157 OUString lcl_toXSD_UNOTime_typed( const css::util::Time& rTime )
160 OUStringBuffer sInfo;
161 lcl_appendInt32ToBuffer( rTime.Hours, sInfo, 2 );
162 sInfo.append( ":" );
163 lcl_appendInt32ToBuffer( rTime.Minutes, sInfo, 2 );
164 sInfo.append( ":" );
165 lcl_appendInt32ToBuffer( rTime.Seconds, sInfo, 2 );
166 if ( rTime.NanoSeconds != 0 )
168 OSL_ENSURE(rTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
169 sInfo.append('.');
170 std::ostringstream ostr;
171 ostr.fill('0');
172 ostr.width(9);
173 ostr << rTime.NanoSeconds;
174 sInfo.append(OUString::createFromAscii(ostr.str().c_str()));
177 return sInfo.makeStringAndClear();
181 OUString lcl_toXSD_UNOTime( const Any& rAny )
183 css::util::Time aTime;
184 OSL_VERIFY( rAny >>= aTime );
185 return lcl_toXSD_UNOTime_typed( aTime );
189 css::util::Time lcl_toUNOTime( const OUString& rString )
191 css::util::Time aTime;
193 bool bWellformed = ISO8601parseTime(rString, aTime);
195 // sanity checks
196 // note that Seconds == 60 denotes leap seconds. Normally, they're not allowed everywhere,
197 // but we accept them all the time for simplicity reasons
198 if ( ( aTime.Hours > 24 )
199 || ( aTime.Minutes > 59 )
200 || ( aTime.Seconds > 60 )
202 bWellformed = false;
204 if ( bWellformed
205 && ( aTime.Hours == 24 )
206 && ( ( aTime.Minutes != 0 )
207 || ( aTime.Seconds != 0 )
208 || ( aTime.NanoSeconds != 0 )
211 bWellformed = false;
213 // all okay?
214 if ( !bWellformed )
215 return css::util::Time();
217 return aTime;
221 Any lcl_toAny_UNOTime( const OUString& rString )
223 return makeAny( lcl_toUNOTime( rString ) );
227 OUString lcl_toXSD_UNODateTime( const Any& rAny )
229 css::util::DateTime aDateTime;
230 OSL_VERIFY( rAny >>= aDateTime );
232 css::util::Date aDate( aDateTime.Day, aDateTime.Month, aDateTime.Year );
233 OUString sDate = lcl_toXSD_UNODate_typed( aDate );
235 css::util::Time const aTime( aDateTime.NanoSeconds, aDateTime.Seconds,
236 aDateTime.Minutes, aDateTime.Hours, aDateTime.IsUTC);
237 OUString sTime = lcl_toXSD_UNOTime_typed( aTime );
239 OUString sRet = sDate + "T" + sTime;
240 return sRet;
244 Any lcl_toAny_UNODateTime( const OUString& rString )
246 // separate the date from the time part
247 sal_Int32 nDateTimeSep = rString.indexOf( 'T' );
248 if ( nDateTimeSep == -1 )
249 nDateTimeSep = rString.indexOf( 't' );
251 css::util::Date aDate;
252 css::util::Time aTime;
253 if ( nDateTimeSep == -1 )
254 { // no time part
255 aDate = lcl_toUNODate( rString );
257 else
259 aDate = lcl_toUNODate( rString.copy( 0, nDateTimeSep ) );
260 aTime = lcl_toUNOTime( rString.copy( nDateTimeSep + 1 ) );
262 css::util::DateTime aDateTime(
263 aTime.NanoSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours,
264 aDate.Day, aDate.Month, aDate.Year, aTime.IsUTC
266 return makeAny( aDateTime );
271 void Convert::init()
273 ADD_ENTRY( this, OUString );
274 ADD_ENTRY( this, bool );
275 ADD_ENTRY( this, double );
276 maMap[ cppu::UnoType<css::util::Date>::get() ] = Convert_t( &lcl_toXSD_UNODate, &lcl_toAny_UNODate );
277 maMap[ cppu::UnoType<css::util::Time>::get() ] = Convert_t( &lcl_toXSD_UNOTime, &lcl_toAny_UNOTime );
278 maMap[ cppu::UnoType<css::util::DateTime>::get() ] = Convert_t( &lcl_toXSD_UNODateTime, &lcl_toAny_UNODateTime );
282 Convert& Convert::get()
284 // create our Singleton instance on demand
285 static Convert aConvert;
286 return aConvert;
289 bool Convert::hasType( const css::uno::Type& rType )
291 return maMap.find( rType ) != maMap.end();
294 css::uno::Sequence<css::uno::Type> Convert::getTypes() const
296 return comphelper::mapKeysToSequence( maMap );
299 OUString Convert::toXSD( const css::uno::Any& rAny )
301 Map_t::iterator aIter = maMap.find( rAny.getValueType() );
302 return aIter != maMap.end() ? aIter->second.first( rAny ) : OUString();
305 css::uno::Any Convert::toAny( const OUString& rValue,
306 const css::uno::Type& rType )
308 Map_t::iterator aIter = maMap.find( rType );
309 return aIter != maMap.end() ? aIter->second.second( rValue ) : css::uno::Any();
313 OUString Convert::collapseWhitespace( const OUString& _rString )
315 sal_Int32 nLength = _rString.getLength();
316 OUStringBuffer aBuffer( nLength );
317 const sal_Unicode* pStr = _rString.getStr();
318 bool bStrip = true;
319 for( sal_Int32 i = 0; i < nLength; i++ )
321 sal_Unicode c = pStr[i];
322 if( c == u'\x0008' ||
323 c == u'\x000A' ||
324 c == u'\x000D' ||
325 c == u' ' )
327 if( ! bStrip )
329 aBuffer.append( u' ' );
330 bStrip = true;
333 else
335 bStrip = false;
336 aBuffer.append( c );
339 if( aBuffer[ aBuffer.getLength() - 1 ] == u' ' )
340 aBuffer.setLength( aBuffer.getLength() - 1 );
341 return aBuffer.makeStringAndClear();
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */