Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "convert.hxx"
31 : :
32 : : #include "unohelper.hxx"
33 : : #include <memory>
34 : : #include <algorithm>
35 : : #include <functional>
36 : : #include <o3tl/compat_functional.hxx>
37 : : #include <rtl/math.hxx>
38 : : #include <rtl/ustrbuf.hxx>
39 : : #include <tools/date.hxx>
40 : : #include <com/sun/star/uno/Type.hxx>
41 : : #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
42 : : #include <com/sun/star/util/Date.hpp>
43 : : #include <com/sun/star/util/DateTime.hpp>
44 : : #include <com/sun/star/util/Time.hpp>
45 : :
46 : : using xforms::Convert;
47 : : using ::rtl::OUString;
48 : : using ::rtl::OUStringBuffer;
49 : : using com::sun::star::uno::Any;
50 : : using com::sun::star::uno::makeAny;
51 : : using com::sun::star::util::Time;
52 : : using namespace std;
53 : : using namespace o3tl;
54 : :
55 : : typedef com::sun::star::util::Date UNODate;
56 : : typedef com::sun::star::util::Time UNOTime;
57 : : typedef com::sun::star::util::DateTime UNODateTime;
58 : :
59 : 0 : Convert::Convert()
60 : 0 : : maMap()
61 : : {
62 [ # # ]: 0 : init();
63 : 0 : }
64 : :
65 : : #define ADD_ENTRY(XCONVERT,TYPE) XCONVERT->maMap[ getCppuType( static_cast<TYPE*>( NULL ) ) ] = Convert_t( &lcl_toXSD_##TYPE, &lcl_toAny_##TYPE )
66 : :
67 : : namespace
68 : : {
69 : : // ========================================================================
70 : 0 : struct StringToken
71 : : {
72 : : private:
73 : : ::rtl::OUString m_sString;
74 : : sal_Int32 m_nTokenStart;
75 : : sal_Int32 m_nTokenEnd;
76 : :
77 : : public:
78 : 0 : StringToken() : m_sString(), m_nTokenStart( 0 ), m_nTokenEnd( 0 ) { }
79 : : StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd );
80 : : StringToken( const StringToken& );
81 : : StringToken& operator=( const StringToken& );
82 : :
83 : 0 : inline bool isEmpty() const { return m_nTokenEnd <= m_nTokenStart; }
84 : : inline sal_Int32 getLength() const { return isEmpty() ? 0 : m_nTokenEnd - m_nTokenStart - 1; }
85 : 0 : inline const sal_Unicode* begin() const { return m_sString.getStr() + m_nTokenStart; }
86 : 0 : inline const sal_Unicode* end() const { return m_sString.getStr() + m_nTokenEnd; }
87 : :
88 : : bool toInt32( sal_Int32& _rValue ) const;
89 : : };
90 : :
91 : : // ------------------------------------------------------------------------
92 : 0 : StringToken::StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd )
93 : : :m_sString( _rString )
94 : : ,m_nTokenStart( _nTokenStart )
95 : 0 : ,m_nTokenEnd( _nTokenEnd )
96 : : {
97 : : OSL_ENSURE( ( m_nTokenStart >= 0 ) && ( m_nTokenStart <= m_sString.getLength() ), "StringToken::StringToken: invalid token start!" );
98 : : OSL_ENSURE( ( m_nTokenEnd >= 0 ) && ( m_nTokenEnd <= m_sString.getLength() ), "StringToken::StringToken: invalid token end!" );
99 : 0 : }
100 : :
101 : : // ------------------------------------------------------------------------
102 : 0 : StringToken::StringToken( const StringToken& _rRHS )
103 : : {
104 : 0 : *this = _rRHS;
105 : 0 : }
106 : :
107 : : // ------------------------------------------------------------------------
108 : 0 : StringToken& StringToken::operator=( const StringToken& _rRHS )
109 : : {
110 [ # # ]: 0 : if ( this == &_rRHS )
111 : 0 : return *this;
112 : :
113 : 0 : m_sString = _rRHS.m_sString;
114 : 0 : m_nTokenStart = _rRHS.m_nTokenStart;
115 : 0 : m_nTokenEnd = _rRHS.m_nTokenEnd;
116 : :
117 : 0 : return *this;
118 : : }
119 : :
120 : : // ------------------------------------------------------------------------
121 : 0 : bool StringToken::toInt32( sal_Int32& _rValue ) const
122 : : {
123 [ # # ]: 0 : if ( isEmpty() )
124 : 0 : return false;
125 : :
126 : 0 : _rValue = 0;
127 : 0 : const sal_Unicode* pStr = begin();
128 [ # # ]: 0 : while ( pStr < end() )
129 : : {
130 [ # # ][ # # ]: 0 : if ( ( *pStr < '0' ) || ( *pStr > '9' ) )
131 : 0 : return false;
132 : :
133 : 0 : _rValue *= 10;
134 : 0 : _rValue += ( *pStr - '0' );
135 : :
136 : 0 : ++pStr;
137 : : }
138 : :
139 : 0 : return true;
140 : : }
141 : :
142 : : // ========================================================================
143 : 0 : class StringTokenizer
144 : : {
145 : : private:
146 : : ::rtl::OUString m_sString;
147 : : const sal_Unicode m_nTokenSeparator;
148 : : sal_Int32 m_nTokenStart;
149 : :
150 : : public:
151 : : /** constructs a tokenizer
152 : : @param _rString the string to tokenize
153 : : @param _nTokenSeparator the token value. May be 0, in this case the tokenizer
154 : : will recognize exactly one token, being the whole string.
155 : : This may make sense if you want to apply <type>StringToken</type>
156 : : methods to a whole string.
157 : : */
158 : : StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator = ';' );
159 : :
160 : : /// resets the tokenizer to the beginning of the string
161 : : void reset();
162 : :
163 : : /// determines whether there is a next token
164 : : bool hasNextToken() const;
165 : :
166 : : /// retrieves the next token
167 : : StringToken
168 : : getNextToken();
169 : : };
170 : :
171 : : // ------------------------------------------------------------------------
172 : 0 : StringTokenizer::StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator )
173 : : :m_sString( _rString )
174 : 0 : ,m_nTokenSeparator( _nTokenSeparator )
175 : : {
176 : 0 : reset();
177 : 0 : }
178 : :
179 : : // ------------------------------------------------------------------------
180 : 0 : void StringTokenizer::reset()
181 : : {
182 : 0 : m_nTokenStart = 0;
183 : 0 : }
184 : :
185 : : // ------------------------------------------------------------------------
186 : 0 : bool StringTokenizer::hasNextToken() const
187 : : {
188 : 0 : return ( m_nTokenStart < m_sString.getLength() );
189 : : }
190 : :
191 : : // ------------------------------------------------------------------------
192 : 0 : StringToken StringTokenizer::getNextToken()
193 : : {
194 : : OSL_PRECOND( hasNextToken(), "StringTokenizer::getNextToken: there is no next token!" );
195 [ # # ]: 0 : if ( !hasNextToken() )
196 : 0 : return StringToken();
197 : :
198 : : // determine the end of the current token
199 [ # # ]: 0 : sal_Int32 nTokenEnd = m_nTokenSeparator ? m_sString.indexOf( m_nTokenSeparator, m_nTokenStart ) : m_sString.getLength();
200 [ # # ][ # # ]: 0 : bool bLastToken = !m_nTokenSeparator || ( nTokenEnd == -1 );
201 : :
202 : : // construct a new token
203 [ # # ]: 0 : StringToken aToken( m_sString, m_nTokenStart, bLastToken ? m_sString.getLength() : nTokenEnd );
204 : : // advance
205 [ # # ]: 0 : m_nTokenStart = bLastToken ? m_sString.getLength() : nTokenEnd + 1;
206 : : // outta here
207 [ # # ]: 0 : return aToken;
208 : : }
209 : :
210 : : // ========================================================================
211 : : // ------------------------------------------------------------------------
212 : 0 : OUString lcl_toXSD_OUString( const Any& rAny )
213 : 0 : { OUString sStr; rAny >>= sStr; return sStr; }
214 : :
215 : : // ------------------------------------------------------------------------
216 : 0 : Any lcl_toAny_OUString( const OUString& rStr )
217 [ # # ]: 0 : { Any aAny; aAny <<= rStr; return aAny; }
218 : :
219 : : // ------------------------------------------------------------------------
220 : 0 : OUString lcl_toXSD_bool( const Any& rAny )
221 [ # # ][ # # ]: 0 : { bool b = false; rAny >>= b; return b ? OUSTRING("true") : OUSTRING("false"); }
[ # # ]
222 : :
223 : : // ------------------------------------------------------------------------
224 : 0 : Any lcl_toAny_bool( const OUString& rStr )
225 : : {
226 [ # # ][ # # ]: 0 : bool b = ( rStr == OUSTRING("true") || rStr == OUSTRING("1") );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
227 [ # # ]: 0 : return makeAny( b );
228 : : }
229 : :
230 : : // ------------------------------------------------------------------------
231 : 0 : OUString lcl_toXSD_double( const Any& rAny )
232 : : {
233 : 0 : double f = 0.0;
234 : 0 : rAny >>= f;
235 : :
236 : 0 : return rtl::math::isFinite( f )
237 : : ? rtl::math::doubleToUString( f, rtl_math_StringFormat_Automatic,
238 : : rtl_math_DecimalPlaces_Max, '.',
239 : : sal_True )
240 [ # # ]: 0 : : OUString();
241 : : }
242 : :
243 : : // ------------------------------------------------------------------------
244 : 0 : Any lcl_toAny_double( const OUString& rString )
245 : : {
246 : : rtl_math_ConversionStatus eStatus;
247 : : double f = rtl::math::stringToDouble(
248 : 0 : rString, sal_Unicode('.'), sal_Unicode(','), &eStatus, NULL );
249 [ # # ][ # # ]: 0 : return ( eStatus == rtl_math_ConversionStatus_Ok ) ? makeAny( f ) : Any();
250 : : }
251 : :
252 : : // ------------------------------------------------------------------------
253 : 0 : void lcl_appendInt32ToBuffer( const sal_Int32 _nValue, ::rtl::OUStringBuffer& _rBuffer, sal_Int16 _nMinDigits )
254 : : {
255 [ # # ][ # # ]: 0 : if ( ( _nMinDigits >= 4 ) && ( _nValue < 1000 ) )
256 : 0 : _rBuffer.append( (sal_Unicode)'0' );
257 [ # # ][ # # ]: 0 : if ( ( _nMinDigits >= 3 ) && ( _nValue < 100 ) )
258 : 0 : _rBuffer.append( (sal_Unicode)'0' );
259 [ # # ][ # # ]: 0 : if ( ( _nMinDigits >= 2 ) && ( _nValue < 10 ) )
260 : 0 : _rBuffer.append( (sal_Unicode)'0' );
261 : 0 : _rBuffer.append( _nValue );
262 : 0 : }
263 : :
264 : : // ------------------------------------------------------------------------
265 : 0 : OUString lcl_toXSD_UNODate_typed( const UNODate& rDate )
266 : : {
267 : :
268 : 0 : ::rtl::OUStringBuffer sInfo;
269 [ # # ]: 0 : lcl_appendInt32ToBuffer( rDate.Year, sInfo, 4 );
270 [ # # ]: 0 : sInfo.appendAscii( "-" );
271 [ # # ]: 0 : lcl_appendInt32ToBuffer( rDate.Month, sInfo, 2 );
272 [ # # ]: 0 : sInfo.appendAscii( "-" );
273 [ # # ]: 0 : lcl_appendInt32ToBuffer( rDate.Day, sInfo, 2 );
274 : :
275 [ # # ]: 0 : return sInfo.makeStringAndClear();
276 : : }
277 : :
278 : : // ------------------------------------------------------------------------
279 : 0 : OUString lcl_toXSD_UNODate( const Any& rAny )
280 : : {
281 : 0 : UNODate aDate;
282 [ # # ]: 0 : OSL_VERIFY( rAny >>= aDate );
283 [ # # ]: 0 : return lcl_toXSD_UNODate_typed( aDate );
284 : : }
285 : :
286 : : // ------------------------------------------------------------------------
287 : 0 : UNODate lcl_toUNODate( const OUString& rString )
288 : : {
289 : 0 : bool bWellformed = true;
290 : :
291 : 0 : UNODate aDate( 1, 1, 1900 );
292 : :
293 : 0 : sal_Int32 nToken = 0;
294 [ # # ]: 0 : StringTokenizer aTokenizer( rString, '-' );
295 [ # # ]: 0 : while ( aTokenizer.hasNextToken() )
296 : : {
297 : 0 : sal_Int32 nTokenValue = 0;
298 [ # # ][ # # ]: 0 : if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) )
299 : : {
300 : 0 : bWellformed = false;
301 : : break;
302 : : }
303 : :
304 [ # # ]: 0 : if ( nToken == 0 )
305 : 0 : aDate.Year = (sal_uInt16)nTokenValue;
306 [ # # ]: 0 : else if ( nToken == 1 )
307 : 0 : aDate.Month = (sal_uInt16)nTokenValue;
308 [ # # ]: 0 : else if ( nToken == 2 )
309 : 0 : aDate.Day = (sal_uInt16)nTokenValue;
310 : : else
311 : : {
312 : 0 : bWellformed = false;
313 : : break;
314 : : }
315 : 0 : ++nToken;
316 : : }
317 : :
318 : : // sanity checks
319 [ # # ][ # # ]: 0 : if ( ( aDate.Year > 9999 ) || ( aDate.Month < 1 ) || ( aDate.Month > 12 ) || ( aDate.Day < 1 ) || ( aDate.Day > 31 ) )
[ # # ][ # # ]
[ # # ]
320 : 0 : bWellformed = false;
321 : : else
322 : : {
323 : 0 : ::Date aDateCheck( 1, aDate.Month, aDate.Year );
324 [ # # ][ # # ]: 0 : if ( aDate.Day > aDateCheck.GetDaysInMonth() )
325 : 0 : bWellformed = false;
326 : : }
327 : :
328 : : // all okay?
329 [ # # ]: 0 : if ( !bWellformed )
330 : 0 : return UNODate( 1, 1, 1900 );
331 : :
332 : 0 : return aDate;
333 : : }
334 : :
335 : : // ------------------------------------------------------------------------
336 : 0 : Any lcl_toAny_UNODate( const OUString& rString )
337 : : {
338 [ # # ]: 0 : return makeAny( lcl_toUNODate( rString ) );
339 : : }
340 : :
341 : : // ------------------------------------------------------------------------
342 : 0 : OUString lcl_toXSD_UNOTime_typed( const UNOTime& rTime )
343 : : {
344 : :
345 : 0 : ::rtl::OUStringBuffer sInfo;
346 [ # # ]: 0 : lcl_appendInt32ToBuffer( rTime.Hours, sInfo, 2 );
347 [ # # ]: 0 : sInfo.appendAscii( ":" );
348 [ # # ]: 0 : lcl_appendInt32ToBuffer( rTime.Minutes, sInfo, 2 );
349 [ # # ]: 0 : sInfo.appendAscii( ":" );
350 [ # # ]: 0 : lcl_appendInt32ToBuffer( rTime.Seconds, sInfo, 2 );
351 [ # # ]: 0 : if ( rTime.HundredthSeconds )
352 : : {
353 [ # # ]: 0 : sInfo.appendAscii( "." );
354 [ # # ]: 0 : lcl_appendInt32ToBuffer( rTime.HundredthSeconds, sInfo, 2 );
355 : : }
356 : :
357 [ # # ]: 0 : return sInfo.makeStringAndClear();
358 : : }
359 : :
360 : : // ------------------------------------------------------------------------
361 : 0 : OUString lcl_toXSD_UNOTime( const Any& rAny )
362 : : {
363 : 0 : UNOTime aTime;
364 [ # # ]: 0 : OSL_VERIFY( rAny >>= aTime );
365 [ # # ]: 0 : return lcl_toXSD_UNOTime_typed( aTime );
366 : : }
367 : :
368 : : // ------------------------------------------------------------------------
369 : 0 : UNOTime lcl_toUNOTime( const OUString& rString )
370 : : {
371 : 0 : bool bWellformed = true;
372 : :
373 : 0 : UNOTime aTime( 0, 0, 0, 0 );
374 : :
375 : 0 : ::rtl::OUString sString( rString );
376 : : // see if there's a decimal separator for the seconds,
377 : : // and if so, handle it separately
378 : 0 : sal_Int32 nDecimalSepPos = rString.indexOf( '.' );
379 [ # # ]: 0 : if ( nDecimalSepPos == -1 )
380 : : // ISO 8601 allows for both a comma and a dot
381 : 0 : nDecimalSepPos = rString.indexOf( ',' );
382 [ # # ]: 0 : if ( nDecimalSepPos != -1 )
383 : : {
384 : : // handle fractional seconds
385 : 0 : ::rtl::OUString sFractional = sString.copy( nDecimalSepPos + 1 );
386 [ # # ]: 0 : if ( sFractional.getLength() > 2 )
387 : : // our precision is HundrethSeconds - it's all a css.util.Time can hold
388 : 0 : sFractional = sFractional.copy( 0, 2 );
389 [ # # ]: 0 : if ( !sFractional.isEmpty() )
390 : : {
391 : 0 : sal_Int32 nFractional = 0;
392 [ # # ][ # # ]: 0 : if ( StringTokenizer( sFractional, 0 ).getNextToken().toInt32( nFractional ) )
[ # # ]
393 : : {
394 : 0 : aTime.HundredthSeconds = (sal_uInt16)nFractional;
395 [ # # ]: 0 : if ( nFractional < 10 )
396 : 0 : aTime.HundredthSeconds *= 10;
397 : : }
398 : : else
399 : 0 : bWellformed = false;
400 : : }
401 : :
402 : : // strip the fraction before further processing
403 : 0 : sString = sString.copy( 0, nDecimalSepPos );
404 : : }
405 : :
406 : : // split into the tokens which are separated by colon
407 : 0 : sal_Int32 nToken = 0;
408 [ # # ]: 0 : StringTokenizer aTokenizer( sString, ':' );
409 [ # # ]: 0 : while ( aTokenizer.hasNextToken() )
410 : : {
411 : 0 : sal_Int32 nTokenValue = 0;
412 [ # # ][ # # ]: 0 : if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) )
413 : : {
414 : 0 : bWellformed = false;
415 : : break;
416 : : }
417 : :
418 [ # # ]: 0 : if ( nToken == 0 )
419 : 0 : aTime.Hours = (sal_uInt16)nTokenValue;
420 [ # # ]: 0 : else if ( nToken == 1 )
421 : 0 : aTime.Minutes = (sal_uInt16)nTokenValue;
422 [ # # ]: 0 : else if ( nToken == 2 )
423 : 0 : aTime.Seconds = (sal_uInt16)nTokenValue;
424 : : else
425 : : {
426 : 0 : bWellformed = false;
427 : : break;
428 : : }
429 : 0 : ++nToken;
430 : : }
431 : :
432 : : // sanity checks
433 : : // note that Seconds == 60 denotes leap seconds. Normally, they're not allowed everywhere,
434 : : // but we accept them all the time for simplicity reasons
435 [ # # ][ # # ]: 0 : if ( ( aTime.Hours > 24 )
[ # # ]
436 : : || ( aTime.Minutes > 59 )
437 : : || ( aTime.Seconds > 60 )
438 : : )
439 : 0 : bWellformed = false;
440 : :
441 [ # # ][ # # ]: 0 : if ( bWellformed
[ # # ][ # # ]
[ # # ]
442 : : && ( aTime.Hours == 24 )
443 : : && ( ( aTime.Minutes != 0 )
444 : : || ( aTime.Seconds != 0 )
445 : : || ( aTime.HundredthSeconds != 0 )
446 : : )
447 : : )
448 : 0 : bWellformed = false;
449 : :
450 : : // all okay?
451 [ # # ]: 0 : if ( !bWellformed )
452 : 0 : return UNOTime( 0, 0, 0, 0 );
453 : :
454 : 0 : return aTime;
455 : : }
456 : :
457 : : // ------------------------------------------------------------------------
458 : 0 : Any lcl_toAny_UNOTime( const OUString& rString )
459 : : {
460 [ # # ]: 0 : return makeAny( lcl_toUNOTime( rString ) );
461 : : }
462 : :
463 : : // ------------------------------------------------------------------------
464 : 0 : OUString lcl_toXSD_UNODateTime( const Any& rAny )
465 : : {
466 : 0 : UNODateTime aDateTime;
467 [ # # ]: 0 : OSL_VERIFY( rAny >>= aDateTime );
468 : :
469 : 0 : UNODate aDate( aDateTime.Day, aDateTime.Month, aDateTime.Year );
470 [ # # ]: 0 : ::rtl::OUString sDate = lcl_toXSD_UNODate_typed( aDate );
471 : :
472 : 0 : UNOTime aTime( aDateTime.HundredthSeconds, aDateTime.Seconds, aDateTime.Minutes, aDateTime.Hours );
473 [ # # ]: 0 : ::rtl::OUString sTime = lcl_toXSD_UNOTime_typed( aTime );
474 : :
475 : 0 : ::rtl::OUStringBuffer sInfo;
476 [ # # ]: 0 : sInfo.append( sDate );
477 [ # # ]: 0 : sInfo.append( (sal_Unicode) 'T' );
478 [ # # ]: 0 : sInfo.append( sTime );
479 [ # # ]: 0 : return sInfo.makeStringAndClear();
480 : : }
481 : :
482 : : // ------------------------------------------------------------------------
483 : 0 : Any lcl_toAny_UNODateTime( const OUString& rString )
484 : : {
485 : : // separate the date from the time part
486 : 0 : sal_Int32 nDateTimeSep = rString.indexOf( 'T' );
487 [ # # ]: 0 : if ( nDateTimeSep == -1 )
488 : 0 : nDateTimeSep = rString.indexOf( 't' );
489 : :
490 : 0 : UNODate aDate;
491 : 0 : UNOTime aTime;
492 [ # # ]: 0 : if ( nDateTimeSep == -1 )
493 : : { // no time part
494 [ # # ]: 0 : aDate = lcl_toUNODate( rString );
495 : 0 : aTime = UNOTime( 0, 0, 0, 0 );
496 : : }
497 : : else
498 : : {
499 [ # # ]: 0 : aDate = lcl_toUNODate( rString.copy( 0, nDateTimeSep ) );
500 [ # # ]: 0 : aTime = lcl_toUNOTime( rString.copy( nDateTimeSep + 1 ) );
501 : : }
502 : : UNODateTime aDateTime(
503 : : aTime.HundredthSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours,
504 : : aDate.Day, aDate.Month, aDate.Year
505 : 0 : );
506 [ # # ]: 0 : return makeAny( aDateTime );
507 : : }
508 : : }
509 : :
510 : : // ============================================================================
511 : 0 : void Convert::init()
512 : : {
513 [ # # ][ # # ]: 0 : ADD_ENTRY( this, OUString );
514 [ # # ][ # # ]: 0 : ADD_ENTRY( this, bool );
515 [ # # ][ # # ]: 0 : ADD_ENTRY( this, double );
516 [ # # ][ # # ]: 0 : ADD_ENTRY( this, UNODate );
517 [ # # ][ # # ]: 0 : ADD_ENTRY( this, UNOTime );
518 [ # # ][ # # ]: 0 : ADD_ENTRY( this, UNODateTime );
519 : 0 : }
520 : :
521 : :
522 : 0 : Convert& Convert::get()
523 : : {
524 : : // create our Singleton instance on demand
525 : : static Convert* pConvert = NULL;
526 [ # # ]: 0 : if( pConvert == NULL )
527 [ # # ]: 0 : pConvert = new Convert();
528 : :
529 : : OSL_ENSURE( pConvert != NULL, "no converter?" );
530 : 0 : return *pConvert;
531 : : }
532 : :
533 : 0 : bool Convert::hasType( const Type_t& rType )
534 : : {
535 [ # # ]: 0 : return maMap.find( rType ) != maMap.end();
536 : : }
537 : :
538 : 0 : Convert::Types_t Convert::getTypes()
539 : : {
540 : 0 : Types_t aTypes( maMap.size() );
541 : : transform( maMap.begin(), maMap.end(), aTypes.getArray(),
542 [ # # ][ # # ]: 0 : o3tl::select1st<Map_t::value_type>() );
543 : 0 : return aTypes;
544 : : }
545 : :
546 : 0 : rtl::OUString Convert::toXSD( const Any_t& rAny )
547 : : {
548 [ # # ]: 0 : Map_t::iterator aIter = maMap.find( rAny.getValueType() );
549 [ # # ][ # # ]: 0 : return aIter != maMap.end() ? aIter->second.first( rAny ) : OUString();
550 : : }
551 : :
552 : 0 : Convert::Any_t Convert::toAny( const rtl::OUString& rValue,
553 : : const Type_t& rType )
554 : : {
555 [ # # ]: 0 : Map_t::iterator aIter = maMap.find( rType );
556 [ # # ][ # # ]: 0 : return aIter != maMap.end() ? aIter->second.second( rValue ) : Any_t();
557 : : }
558 : :
559 : : //------------------------------------------------------------------------
560 : 0 : ::rtl::OUString Convert::convertWhitespace( const ::rtl::OUString& _rString, sal_Int16 _nWhitespaceTreatment )
561 : : {
562 : 0 : ::rtl::OUString sConverted;
563 [ # # # ]: 0 : switch( _nWhitespaceTreatment )
564 : : {
565 : : default:
566 : : OSL_FAIL( "Convert::convertWhitespace: invalid whitespace treatment constant!" );
567 : : // NO break
568 : : case com::sun::star::xsd::WhiteSpaceTreatment::Preserve:
569 : 0 : sConverted = _rString;
570 : 0 : break;
571 : : case com::sun::star::xsd::WhiteSpaceTreatment::Replace:
572 [ # # ]: 0 : sConverted = replaceWhitespace( _rString );
573 : 0 : break;
574 : : case com::sun::star::xsd::WhiteSpaceTreatment::Collapse:
575 [ # # ]: 0 : sConverted = collapseWhitespace( _rString );
576 : 0 : break;
577 : : }
578 : 0 : return sConverted;
579 : : }
580 : :
581 : : //------------------------------------------------------------------------
582 : 0 : ::rtl::OUString Convert::replaceWhitespace( const ::rtl::OUString& _rString )
583 : : {
584 [ # # ]: 0 : OUStringBuffer aBuffer( _rString );
585 : 0 : sal_Int32 nLength = aBuffer.getLength();
586 : 0 : const sal_Unicode* pBuffer = aBuffer.getStr();
587 [ # # ]: 0 : for( sal_Int32 i = 0; i < nLength; i++ )
588 : : {
589 : 0 : sal_Unicode c = pBuffer[i];
590 [ # # ][ # # ]: 0 : if( c == sal_Unicode(0x08) ||
[ # # ]
591 : : c == sal_Unicode(0x0A) ||
592 : : c == sal_Unicode(0x0D) )
593 : 0 : aBuffer[i] = sal_Unicode(0x20);
594 : : }
595 [ # # ]: 0 : return aBuffer.makeStringAndClear();
596 : : }
597 : :
598 : : //------------------------------------------------------------------------
599 : 0 : ::rtl::OUString Convert::collapseWhitespace( const ::rtl::OUString& _rString )
600 : : {
601 : 0 : sal_Int32 nLength = _rString.getLength();
602 : 0 : OUStringBuffer aBuffer( nLength );
603 : 0 : const sal_Unicode* pStr = _rString.getStr();
604 : 0 : bool bStrip = true;
605 [ # # ]: 0 : for( sal_Int32 i = 0; i < nLength; i++ )
606 : : {
607 : 0 : sal_Unicode c = pStr[i];
608 [ # # ][ # # ]: 0 : if( c == sal_Unicode(0x08) ||
[ # # ][ # # ]
609 : : c == sal_Unicode(0x0A) ||
610 : : c == sal_Unicode(0x0D) ||
611 : : c == sal_Unicode(0x20) )
612 : : {
613 [ # # ]: 0 : if( ! bStrip )
614 : : {
615 [ # # ]: 0 : aBuffer.append( sal_Unicode(0x20) );
616 : 0 : bStrip = true;
617 : : }
618 : : }
619 : : else
620 : : {
621 : 0 : bStrip = false;
622 [ # # ]: 0 : aBuffer.append( c );
623 : : }
624 : : }
625 [ # # ]: 0 : if( aBuffer[ aBuffer.getLength() - 1 ] == sal_Unicode( 0x20 ) )
626 [ # # ]: 0 : aBuffer.setLength( aBuffer.getLength() - 1 );
627 [ # # ]: 0 : return aBuffer.makeStringAndClear();
628 : : }
629 : :
630 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|