Line data Source code
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 <sax/tools/converter.hxx>
21 :
22 : #include <com/sun/star/i18n/UnicodeType.hpp>
23 : #include <com/sun/star/util/DateTime.hpp>
24 : #include <com/sun/star/util/Date.hpp>
25 : #include <com/sun/star/util/DateTimeWithTimezone.hpp>
26 : #include <com/sun/star/util/DateWithTimezone.hpp>
27 : #include <com/sun/star/util/Duration.hpp>
28 : #include <com/sun/star/util/Time.hpp>
29 : #include <com/sun/star/uno/Sequence.hxx>
30 :
31 : #include <rtl/ustrbuf.hxx>
32 : #include <rtl/math.hxx>
33 : #include <osl/time.h>
34 :
35 : #include <algorithm>
36 :
37 : using namespace com::sun::star;
38 : using namespace com::sun::star::uno;
39 : using namespace com::sun::star::util;
40 : using namespace ::com::sun::star::i18n;
41 :
42 :
43 : namespace sax {
44 :
45 : static const sal_Char* gpsMM = "mm";
46 : static const sal_Char* gpsCM = "cm";
47 : static const sal_Char* gpsPT = "pt";
48 : static const sal_Char* gpsINCH = "in";
49 : static const sal_Char* gpsPC = "pc";
50 :
51 : const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 14;
52 :
53 : /** convert string to measure using optional min and max values*/
54 0 : bool Converter::convertMeasure( sal_Int32& rValue,
55 : const OUString& rString,
56 : sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
57 : sal_Int32 nMin /* = SAL_MIN_INT32 */,
58 : sal_Int32 nMax /* = SAL_MAX_INT32 */ )
59 : {
60 0 : bool bNeg = false;
61 0 : double nVal = 0;
62 :
63 0 : sal_Int32 nPos = 0;
64 0 : sal_Int32 const nLen = rString.getLength();
65 :
66 : // skip white space
67 0 : while( (nPos < nLen) && (rString[nPos] <= ' ') )
68 0 : nPos++;
69 :
70 0 : if( nPos < nLen && '-' == rString[nPos] )
71 : {
72 0 : bNeg = true;
73 0 : nPos++;
74 : }
75 :
76 : // get number
77 0 : while( nPos < nLen &&
78 0 : '0' <= rString[nPos] &&
79 0 : '9' >= rString[nPos] )
80 : {
81 : // TODO: check overflow!
82 0 : nVal *= 10;
83 0 : nVal += (rString[nPos] - '0');
84 0 : nPos++;
85 : }
86 0 : double nDiv = 1.;
87 0 : if( nPos < nLen && '.' == rString[nPos] )
88 : {
89 0 : nPos++;
90 :
91 0 : while( nPos < nLen &&
92 0 : '0' <= rString[nPos] &&
93 0 : '9' >= rString[nPos] )
94 : {
95 : // TODO: check overflow!
96 0 : nDiv *= 10;
97 0 : nVal += ( ((double)(rString[nPos] - '0')) / nDiv );
98 0 : nPos++;
99 : }
100 : }
101 :
102 : // skip white space
103 0 : while( (nPos < nLen) && (rString[nPos] <= ' ') )
104 0 : nPos++;
105 :
106 0 : if( nPos < nLen )
107 : {
108 :
109 0 : if( MeasureUnit::PERCENT == nTargetUnit )
110 : {
111 0 : if( '%' != rString[nPos] )
112 0 : return false;
113 : }
114 0 : else if( MeasureUnit::PIXEL == nTargetUnit )
115 : {
116 0 : if( nPos + 1 >= nLen ||
117 0 : ('p' != rString[nPos] &&
118 0 : 'P' != rString[nPos])||
119 0 : ('x' != rString[nPos+1] &&
120 0 : 'X' != rString[nPos+1]) )
121 0 : return false;
122 : }
123 : else
124 : {
125 : OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
126 : MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported");
127 0 : const sal_Char *aCmpsL[2] = { 0, 0 };
128 0 : const sal_Char *aCmpsU[2] = { 0, 0 };
129 0 : double aScales[2] = { 1., 1. };
130 :
131 0 : if( MeasureUnit::TWIP == nTargetUnit )
132 : {
133 0 : switch( rString[nPos] )
134 : {
135 : case sal_Unicode('c'):
136 : case sal_Unicode('C'):
137 0 : aCmpsL[0] = "cm";
138 0 : aCmpsU[0] = "CM";
139 0 : aScales[0] = (72.*20.)/2.54; // twip
140 0 : break;
141 : case sal_Unicode('i'):
142 : case sal_Unicode('I'):
143 0 : aCmpsL[0] = "in";
144 0 : aCmpsU[0] = "IN";
145 0 : aScales[0] = 72.*20.; // twip
146 0 : break;
147 : case sal_Unicode('m'):
148 : case sal_Unicode('M'):
149 0 : aCmpsL[0] = "mm";
150 0 : aCmpsU[0] = "MM";
151 0 : aScales[0] = (72.*20.)/25.4; // twip
152 0 : break;
153 : case sal_Unicode('p'):
154 : case sal_Unicode('P'):
155 0 : aCmpsL[0] = "pt";
156 0 : aCmpsU[0] = "PT";
157 0 : aScales[0] = 20.; // twip
158 :
159 0 : aCmpsL[1] = "pc";
160 0 : aCmpsU[1] = "PC";
161 0 : aScales[1] = 12.*20.; // twip
162 0 : break;
163 : }
164 : }
165 0 : else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
166 : {
167 0 : double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0;
168 0 : switch( rString[nPos] )
169 : {
170 : case sal_Unicode('c'):
171 : case sal_Unicode('C'):
172 0 : aCmpsL[0] = "cm";
173 0 : aCmpsU[0] = "CM";
174 0 : aScales[0] = 10.0 * nScaleFactor; // mm/100
175 0 : break;
176 : case sal_Unicode('i'):
177 : case sal_Unicode('I'):
178 0 : aCmpsL[0] = "in";
179 0 : aCmpsU[0] = "IN";
180 0 : aScales[0] = 1000.*2.54; // mm/100
181 0 : break;
182 : case sal_Unicode('m'):
183 : case sal_Unicode('M'):
184 0 : aCmpsL[0] = "mm";
185 0 : aCmpsU[0] = "MM";
186 0 : aScales[0] = 1.0 * nScaleFactor; // mm/100
187 0 : break;
188 : case sal_Unicode('p'):
189 : case sal_Unicode('P'):
190 0 : aCmpsL[0] = "pt";
191 0 : aCmpsU[0] = "PT";
192 0 : aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
193 :
194 0 : aCmpsL[1] = "pc";
195 0 : aCmpsU[1] = "PC";
196 0 : aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
197 0 : break;
198 0 : }
199 : }
200 0 : else if( MeasureUnit::POINT == nTargetUnit )
201 : {
202 0 : if( rString[nPos] == 'p' || rString[nPos] == 'P' )
203 : {
204 0 : aCmpsL[0] = "pt";
205 0 : aCmpsU[0] = "PT";
206 0 : aScales[0] = 1;
207 : }
208 : }
209 :
210 0 : if( aCmpsL[0] == NULL )
211 0 : return false;
212 :
213 0 : double nScale = 0.;
214 0 : for( sal_uInt16 i= 0; i < 2; i++ )
215 : {
216 0 : const sal_Char *pL = aCmpsL[i];
217 0 : if( pL )
218 : {
219 0 : const sal_Char *pU = aCmpsU[i];
220 0 : while( nPos < nLen && *pL )
221 : {
222 0 : sal_Unicode c = rString[nPos];
223 0 : if( c != *pL && c != *pU )
224 0 : break;
225 0 : pL++;
226 0 : pU++;
227 0 : nPos++;
228 : }
229 0 : if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
230 : {
231 0 : nScale = aScales[i];
232 0 : break;
233 : }
234 : }
235 : }
236 :
237 0 : if( 0. == nScale )
238 0 : return false;
239 :
240 : // TODO: check overflow
241 0 : if( nScale != 1. )
242 0 : nVal *= nScale;
243 : }
244 : }
245 :
246 0 : nVal += .5;
247 0 : if( bNeg )
248 0 : nVal = -nVal;
249 :
250 0 : if( nVal <= (double)nMin )
251 0 : rValue = nMin;
252 0 : else if( nVal >= (double)nMax )
253 0 : rValue = nMax;
254 : else
255 0 : rValue = (sal_Int32)nVal;
256 :
257 0 : return true;
258 : }
259 :
260 : /** convert measure in given unit to string with given unit */
261 0 : void Converter::convertMeasure( OUStringBuffer& rBuffer,
262 : sal_Int32 nMeasure,
263 : sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
264 : sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ )
265 : {
266 0 : if( nSourceUnit == MeasureUnit::PERCENT )
267 : {
268 : OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
269 : "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
270 :
271 0 : rBuffer.append( nMeasure );
272 0 : rBuffer.append( '%' );
273 :
274 0 : return;
275 : }
276 : // the sign is processed separately
277 0 : if( nMeasure < 0 )
278 : {
279 0 : nMeasure = -nMeasure;
280 0 : rBuffer.append( '-' );
281 : }
282 :
283 : // The new length is (nVal * nMul)/(nDiv*nFac*10)
284 0 : long nMul = 1000;
285 0 : long nDiv = 1;
286 0 : long nFac = 100;
287 0 : const sal_Char* psUnit = 0;
288 0 : switch( nSourceUnit )
289 : {
290 : case MeasureUnit::TWIP:
291 0 : switch( nTargetUnit )
292 : {
293 : case MeasureUnit::MM_100TH:
294 : case MeasureUnit::MM_10TH:
295 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
296 : case MeasureUnit::MM:
297 : // 0.01mm = 0.57twip (exactly)
298 0 : nMul = 25400; // 25.4 * 1000
299 0 : nDiv = 1440; // 72 * 20;
300 0 : nFac = 100;
301 0 : psUnit = gpsMM;
302 0 : break;
303 :
304 : case MeasureUnit::CM:
305 : // 0.001cm = 0.57twip (exactly)
306 0 : nMul = 25400; // 2.54 * 10000
307 0 : nDiv = 1440; // 72 * 20;
308 0 : nFac = 1000;
309 0 : psUnit = gpsCM;
310 0 : break;
311 :
312 : case MeasureUnit::POINT:
313 : // 0.01pt = 0.2twip (exactly)
314 0 : nMul = 1000;
315 0 : nDiv = 20;
316 0 : nFac = 100;
317 0 : psUnit = gpsPT;
318 0 : break;
319 :
320 : case MeasureUnit::INCH:
321 : default:
322 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
323 : "output unit not supported for twip values" );
324 : // 0.0001in = 0.144twip (exactly)
325 0 : nMul = 100000;
326 0 : nDiv = 1440; // 72 * 20;
327 0 : nFac = 10000;
328 0 : psUnit = gpsINCH;
329 0 : break;
330 : }
331 0 : break;
332 :
333 : case MeasureUnit::POINT:
334 : // 1pt = 1pt (exactly)
335 : OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
336 : "output unit not supported for pt values" );
337 0 : nMul = 10;
338 0 : nDiv = 1;
339 0 : nFac = 1;
340 0 : psUnit = gpsPT;
341 0 : break;
342 : case MeasureUnit::MM_10TH:
343 : case MeasureUnit::MM_100TH:
344 : {
345 0 : long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
346 0 : switch( nTargetUnit )
347 : {
348 : case MeasureUnit::MM_100TH:
349 : case MeasureUnit::MM_10TH:
350 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
351 : "output unit not supported for 1/100mm values" );
352 : case MeasureUnit::MM:
353 : // 0.01mm = 1 mm/100 (exactly)
354 0 : nMul = 10;
355 0 : nDiv = 1;
356 0 : nFac = nFac2;
357 0 : psUnit = gpsMM;
358 0 : break;
359 :
360 : case MeasureUnit::CM:
361 : // 0.001mm = 1 mm/100 (exactly)
362 0 : nMul = 10;
363 0 : nDiv = 1; // 72 * 20;
364 0 : nFac = 10*nFac2;
365 0 : psUnit = gpsCM;
366 0 : break;
367 :
368 : case MeasureUnit::POINT:
369 : // 0.01pt = 0.35 mm/100 (exactly)
370 0 : nMul = 72000;
371 0 : nDiv = 2540;
372 0 : nFac = nFac2;
373 0 : psUnit = gpsPT;
374 0 : break;
375 :
376 : case MeasureUnit::INCH:
377 : default:
378 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
379 : "output unit not supported for 1/100mm values" );
380 : // 0.0001in = 0.254 mm/100 (exactly)
381 0 : nMul = 100000;
382 0 : nDiv = 2540;
383 0 : nFac = 100*nFac2;
384 0 : psUnit = gpsINCH;
385 0 : break;
386 : }
387 0 : break;
388 : }
389 : default:
390 : OSL_ENSURE(false, "sax::Converter::convertMeasure(): "
391 : "source unit not supported");
392 0 : break;
393 : }
394 :
395 0 : sal_Int64 nValue = nMeasure;
396 : OSL_ENSURE(nValue <= SAL_MAX_INT64 / nMul, "convertMeasure: overflow");
397 0 : nValue *= nMul;
398 0 : nValue /= nDiv;
399 0 : nValue += 5;
400 0 : nValue /= 10;
401 :
402 0 : rBuffer.append( static_cast<sal_Int64>(nValue / nFac) );
403 0 : if (nFac > 1 && (nValue % nFac) != 0)
404 : {
405 0 : rBuffer.append( '.' );
406 0 : while (nFac > 1 && (nValue % nFac) != 0)
407 : {
408 0 : nFac /= 10;
409 0 : rBuffer.append( static_cast<sal_Int32>((nValue / nFac) % 10) );
410 : }
411 : }
412 :
413 0 : if( psUnit )
414 0 : rBuffer.appendAscii( psUnit );
415 : }
416 :
417 0 : static const OUString& getTrueString()
418 : {
419 0 : static const OUString sTrue( "true" );
420 0 : return sTrue;
421 : }
422 :
423 0 : static const OUString& getFalseString()
424 : {
425 0 : static const OUString sFalse( "false" );
426 0 : return sFalse;
427 : }
428 :
429 : /** convert string to boolean */
430 0 : bool Converter::convertBool( bool& rBool, const OUString& rString )
431 : {
432 0 : rBool = rString == getTrueString();
433 :
434 0 : return rBool || (rString == getFalseString());
435 : }
436 :
437 : /** convert boolean to string */
438 0 : void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
439 : {
440 0 : rBuffer.append( bValue ? getTrueString() : getFalseString() );
441 0 : }
442 :
443 : /** convert string to percent */
444 0 : bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString )
445 : {
446 0 : return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
447 : }
448 :
449 : /** convert percent to string */
450 0 : void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
451 : {
452 0 : rBuffer.append( nValue );
453 0 : rBuffer.append( '%' );
454 0 : }
455 :
456 : /** convert string to pixel measure */
457 0 : bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString )
458 : {
459 0 : return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
460 : }
461 :
462 : /** convert pixel measure to string */
463 0 : void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
464 : {
465 0 : rBuffer.append( nValue );
466 0 : rBuffer.append( 'p' );
467 0 : rBuffer.append( 'x' );
468 0 : }
469 :
470 0 : int lcl_gethex( int nChar )
471 : {
472 0 : if( nChar >= '0' && nChar <= '9' )
473 0 : return nChar - '0';
474 0 : else if( nChar >= 'a' && nChar <= 'f' )
475 0 : return nChar - 'a' + 10;
476 0 : else if( nChar >= 'A' && nChar <= 'F' )
477 0 : return nChar - 'A' + 10;
478 : else
479 0 : return 0;
480 : }
481 :
482 : /** convert string to rgb color */
483 0 : bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue )
484 : {
485 0 : if( rValue.getLength() != 7 || rValue[0] != '#' )
486 0 : return false;
487 :
488 0 : rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] );
489 0 : rColor <<= 8;
490 :
491 0 : rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) );
492 0 : rColor <<= 8;
493 :
494 0 : rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) );
495 :
496 0 : return true;
497 : }
498 :
499 : static const sal_Char aHexTab[] = "0123456789abcdef";
500 :
501 : /** convert color to string */
502 0 : void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
503 : {
504 0 : rBuffer.append( '#' );
505 :
506 0 : sal_uInt8 nCol = (sal_uInt8)(nColor >> 16);
507 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
508 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
509 :
510 0 : nCol = (sal_uInt8)(nColor >> 8);
511 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
512 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
513 :
514 0 : nCol = (sal_uInt8)nColor;
515 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
516 0 : rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
517 0 : }
518 :
519 : /** convert number to string */
520 0 : void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber )
521 : {
522 0 : rBuffer.append( nNumber );
523 0 : }
524 :
525 : /** convert string to number with optional min and max values */
526 0 : bool Converter::convertNumber( sal_Int32& rValue,
527 : const OUString& rString,
528 : sal_Int32 nMin, sal_Int32 nMax )
529 : {
530 0 : rValue = 0;
531 0 : sal_Int64 nNumber = 0;
532 0 : bool bRet = convertNumber64(nNumber,rString,nMin,nMax);
533 0 : if ( bRet )
534 0 : rValue = static_cast<sal_Int32>(nNumber);
535 0 : return bRet;
536 : }
537 :
538 : /** convert string to 64-bit number with optional min and max values */
539 0 : bool Converter::convertNumber64( sal_Int64& rValue,
540 : const OUString& rString,
541 : sal_Int64 nMin, sal_Int64 nMax )
542 : {
543 0 : bool bNeg = false;
544 0 : rValue = 0;
545 :
546 0 : sal_Int32 nPos = 0;
547 0 : sal_Int32 const nLen = rString.getLength();
548 :
549 : // skip white space
550 0 : while( (nPos < nLen) && (rString[nPos] <= ' ') )
551 0 : nPos++;
552 :
553 0 : if( nPos < nLen && '-' == rString[nPos] )
554 : {
555 0 : bNeg = true;
556 0 : nPos++;
557 : }
558 :
559 : // get number
560 0 : while( nPos < nLen &&
561 0 : '0' <= rString[nPos] &&
562 0 : '9' >= rString[nPos] )
563 : {
564 : // TODO: check overflow!
565 0 : rValue *= 10;
566 0 : rValue += (rString[nPos] - sal_Unicode('0'));
567 0 : nPos++;
568 : }
569 :
570 0 : if( bNeg )
571 0 : rValue *= -1;
572 :
573 0 : if( rValue < nMin )
574 0 : rValue = nMin;
575 0 : else if( rValue > nMax )
576 0 : rValue = nMax;
577 :
578 0 : return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
579 : }
580 :
581 : /** convert double number to string (using ::rtl::math) */
582 0 : void Converter::convertDouble( OUStringBuffer& rBuffer,
583 : double fNumber,
584 : bool bWriteUnits,
585 : sal_Int16 nSourceUnit,
586 : sal_Int16 nTargetUnit)
587 : {
588 0 : if(MeasureUnit::PERCENT == nSourceUnit)
589 : {
590 : OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
591 0 : ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
592 0 : if(bWriteUnits)
593 0 : rBuffer.append('%');
594 : }
595 : else
596 : {
597 0 : OUStringBuffer sUnit;
598 0 : double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
599 0 : if(fFactor != 1.0)
600 0 : fNumber *= fFactor;
601 0 : ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
602 0 : if(bWriteUnits)
603 0 : rBuffer.append(sUnit.makeStringAndClear());
604 : }
605 0 : }
606 :
607 : /** convert double number to string (using ::rtl::math) */
608 0 : void Converter::convertDouble( OUStringBuffer& rBuffer, double fNumber)
609 : {
610 0 : ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
611 0 : }
612 :
613 : /** convert string to double number (using ::rtl::math) */
614 0 : bool Converter::convertDouble(double& rValue,
615 : const OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
616 : {
617 : rtl_math_ConversionStatus eStatus;
618 0 : rValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, NULL );
619 :
620 0 : if(eStatus == rtl_math_ConversionStatus_Ok)
621 : {
622 0 : OUStringBuffer sUnit;
623 : // fdo#48969: switch source and target because factor is used to divide!
624 : double const fFactor =
625 0 : GetConversionFactor(sUnit, nTargetUnit, nSourceUnit);
626 0 : if(fFactor != 1.0 && fFactor != 0.0)
627 0 : rValue /= fFactor;
628 : }
629 :
630 0 : return ( eStatus == rtl_math_ConversionStatus_Ok );
631 : }
632 :
633 : /** convert string to double number (using ::rtl::math) */
634 0 : bool Converter::convertDouble(double& rValue, const OUString& rString)
635 : {
636 : rtl_math_ConversionStatus eStatus;
637 0 : rValue = ::rtl::math::stringToDouble( rString, '.', ',', &eStatus, NULL );
638 0 : return ( eStatus == rtl_math_ConversionStatus_Ok );
639 : }
640 :
641 : /** convert double to ISO "duration" string; negative durations allowed */
642 0 : void Converter::convertDuration(OUStringBuffer& rBuffer,
643 : const double fTime)
644 : {
645 0 : double fValue = fTime;
646 :
647 : // take care of negative durations as specified in:
648 : // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
649 0 : if (fValue < 0.0)
650 : {
651 0 : rBuffer.append('-');
652 0 : fValue = - fValue;
653 : }
654 :
655 0 : rBuffer.append( "PT" );
656 0 : fValue *= 24;
657 0 : double fHoursValue = ::rtl::math::approxFloor (fValue);
658 0 : fValue -= fHoursValue;
659 0 : fValue *= 60;
660 0 : double fMinsValue = ::rtl::math::approxFloor (fValue);
661 0 : fValue -= fMinsValue;
662 0 : fValue *= 60;
663 0 : double fSecsValue = ::rtl::math::approxFloor (fValue);
664 0 : fValue -= fSecsValue;
665 : double fNanoSecsValue;
666 0 : if (fValue > 0.00000000001)
667 0 : fNanoSecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
668 : else
669 0 : fNanoSecsValue = 0.0;
670 :
671 0 : if (fNanoSecsValue == 1.0)
672 : {
673 0 : fNanoSecsValue = 0.0;
674 0 : fSecsValue += 1.0;
675 : }
676 0 : if (fSecsValue >= 60.0)
677 : {
678 0 : fSecsValue -= 60.0;
679 0 : fMinsValue += 1.0;
680 : }
681 0 : if (fMinsValue >= 60.0)
682 : {
683 0 : fMinsValue -= 60.0;
684 0 : fHoursValue += 1.0;
685 : }
686 :
687 0 : if (fHoursValue < 10)
688 0 : rBuffer.append( '0');
689 0 : rBuffer.append( sal_Int32( fHoursValue));
690 0 : rBuffer.append( 'H');
691 0 : if (fMinsValue < 10)
692 0 : rBuffer.append( '0');
693 0 : rBuffer.append( sal_Int32( fMinsValue));
694 0 : rBuffer.append( 'M');
695 0 : if (fSecsValue < 10)
696 0 : rBuffer.append( '0');
697 0 : rBuffer.append( sal_Int32( fSecsValue));
698 0 : if (fNanoSecsValue > 0.0)
699 : {
700 : OUString aNS( ::rtl::math::doubleToUString( fValue,
701 : rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
702 0 : true));
703 0 : if ( aNS.getLength() > 2 )
704 : {
705 0 : rBuffer.append( '.');
706 0 : rBuffer.append( aNS.copy( 2 ) ); // strip "0."
707 0 : }
708 : }
709 0 : rBuffer.append( 'S');
710 0 : }
711 :
712 : /** convert ISO "duration" string to double; negative durations allowed */
713 0 : bool Converter::convertDuration(double& rfTime,
714 : const OUString& rString)
715 : {
716 0 : OUString aTrimmed = rString.trim().toAsciiUpperCase();
717 0 : const sal_Unicode* pStr = aTrimmed.getStr();
718 :
719 : // negative time duration?
720 0 : bool bIsNegativeDuration = false;
721 0 : if ( '-' == (*pStr) )
722 : {
723 0 : bIsNegativeDuration = true;
724 0 : pStr++;
725 : }
726 :
727 0 : if ( *(pStr++) != 'P' ) // duration must start with "P"
728 0 : return false;
729 :
730 0 : OUString sDoubleStr;
731 0 : bool bSuccess = true;
732 0 : bool bDone = false;
733 0 : bool bTimePart = false;
734 0 : bool bIsFraction = false;
735 0 : sal_Int32 nDays = 0;
736 0 : sal_Int32 nHours = 0;
737 0 : sal_Int32 nMins = 0;
738 0 : sal_Int32 nSecs = 0;
739 0 : sal_Int32 nTemp = 0;
740 :
741 0 : while ( bSuccess && !bDone )
742 : {
743 0 : sal_Unicode c = *(pStr++);
744 0 : if ( !c ) // end
745 0 : bDone = true;
746 0 : else if ( '0' <= c && '9' >= c )
747 : {
748 0 : if ( nTemp >= SAL_MAX_INT32 / 10 )
749 0 : bSuccess = false;
750 : else
751 : {
752 0 : if ( !bIsFraction )
753 : {
754 0 : nTemp *= 10;
755 0 : nTemp += (c - sal_Unicode('0'));
756 : }
757 : else
758 : {
759 0 : sDoubleStr += OUString(c);
760 : }
761 : }
762 : }
763 0 : else if ( bTimePart )
764 : {
765 0 : if ( c == 'H' )
766 : {
767 0 : nHours = nTemp;
768 0 : nTemp = 0;
769 : }
770 0 : else if ( c == 'M' )
771 : {
772 0 : nMins = nTemp;
773 0 : nTemp = 0;
774 : }
775 0 : else if ( (c == ',') || (c == '.') )
776 : {
777 0 : nSecs = nTemp;
778 0 : nTemp = 0;
779 0 : bIsFraction = true;
780 0 : sDoubleStr = "0.";
781 : }
782 0 : else if ( c == 'S' )
783 : {
784 0 : if ( !bIsFraction )
785 : {
786 0 : nSecs = nTemp;
787 0 : nTemp = 0;
788 0 : sDoubleStr = "0.0";
789 : }
790 : }
791 : else
792 0 : bSuccess = false; // invalid character
793 : }
794 : else
795 : {
796 0 : if ( c == 'T' ) // "T" starts time part
797 0 : bTimePart = true;
798 0 : else if ( c == 'D' )
799 : {
800 0 : nDays = nTemp;
801 0 : nTemp = 0;
802 : }
803 0 : else if ( c == 'Y' || c == 'M' )
804 : {
805 : //! how many days is a year or month?
806 :
807 : OSL_FAIL( "years or months in duration: not implemented");
808 0 : bSuccess = false;
809 : }
810 : else
811 0 : bSuccess = false; // invalid character
812 : }
813 : }
814 :
815 0 : if ( bSuccess )
816 : {
817 0 : if ( nDays )
818 0 : nHours += nDays * 24; // add the days to the hours part
819 0 : double fTempTime = 0.0;
820 0 : double fHour = nHours;
821 0 : double fMin = nMins;
822 0 : double fSec = nSecs;
823 0 : double fFraction = sDoubleStr.toDouble();
824 0 : fTempTime = fHour / 24;
825 0 : fTempTime += fMin / (24 * 60);
826 0 : fTempTime += fSec / (24 * 60 * 60);
827 0 : fTempTime += fFraction / (24 * 60 * 60);
828 :
829 : // negative duration?
830 0 : if ( bIsNegativeDuration )
831 : {
832 0 : fTempTime = -fTempTime;
833 : }
834 :
835 0 : rfTime = fTempTime;
836 : }
837 0 : return bSuccess;
838 : }
839 :
840 : /** convert util::Duration to ISO8601 "duration" string */
841 0 : void Converter::convertDuration(OUStringBuffer& rBuffer,
842 : const ::util::Duration& rDuration)
843 : {
844 0 : if (rDuration.Negative)
845 : {
846 0 : rBuffer.append('-');
847 : }
848 0 : rBuffer.append('P');
849 0 : const bool bHaveDate(rDuration.Years != 0 ||
850 0 : rDuration.Months != 0 ||
851 0 : rDuration.Days != 0);
852 0 : if (rDuration.Years)
853 : {
854 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
855 0 : rBuffer.append('Y');
856 : }
857 0 : if (rDuration.Months)
858 : {
859 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
860 0 : rBuffer.append('M');
861 : }
862 0 : if (rDuration.Days)
863 : {
864 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
865 0 : rBuffer.append('D');
866 : }
867 0 : if ( rDuration.Hours != 0
868 0 : || rDuration.Minutes != 0
869 0 : || rDuration.Seconds != 0
870 0 : || rDuration.NanoSeconds != 0 )
871 : {
872 0 : rBuffer.append('T'); // time separator
873 0 : if (rDuration.Hours)
874 : {
875 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
876 0 : rBuffer.append('H');
877 : }
878 0 : if (rDuration.Minutes)
879 : {
880 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
881 0 : rBuffer.append('M');
882 : }
883 0 : if (rDuration.Seconds != 0 || rDuration.NanoSeconds != 0)
884 : {
885 : // seconds must not be omitted (i.e. ".42S" is not valid)
886 0 : rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
887 0 : if (rDuration.NanoSeconds)
888 : {
889 : OSL_ENSURE(rDuration.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
890 0 : rBuffer.append('.');
891 0 : std::ostringstream ostr;
892 0 : ostr.fill('0');
893 0 : ostr.width(9);
894 0 : ostr << rDuration.NanoSeconds;
895 0 : rBuffer.append(OUString::createFromAscii(ostr.str().c_str()));
896 : }
897 0 : rBuffer.append('S');
898 0 : }
899 : }
900 0 : else if (!bHaveDate)
901 : {
902 : // zero duration: XMLSchema-2 says there must be at least one component
903 0 : rBuffer.append('0');
904 0 : rBuffer.append('D');
905 : }
906 0 : }
907 :
908 : enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
909 :
910 : static Result
911 0 : readUnsignedNumber(const OUString & rString,
912 : sal_Int32 & io_rnPos, sal_Int32 & o_rNumber)
913 : {
914 0 : bool bOverflow(false);
915 0 : sal_Int64 nTemp(0);
916 0 : sal_Int32 nPos(io_rnPos);
917 :
918 0 : while (nPos < rString.getLength())
919 : {
920 0 : const sal_Unicode c = rString[nPos];
921 0 : if (('0' <= c) && (c <= '9'))
922 : {
923 0 : nTemp *= 10;
924 0 : nTemp += (c - sal_Unicode('0'));
925 0 : if (nTemp >= SAL_MAX_INT32)
926 : {
927 0 : bOverflow = true;
928 : }
929 : }
930 : else
931 : {
932 : break;
933 : }
934 0 : ++nPos;
935 : }
936 :
937 0 : if (io_rnPos == nPos) // read something?
938 : {
939 0 : o_rNumber = -1;
940 0 : return R_NOTHING;
941 : }
942 :
943 0 : io_rnPos = nPos;
944 0 : o_rNumber = nTemp;
945 0 : return (bOverflow) ? R_OVERFLOW : R_SUCCESS;
946 : }
947 :
948 : static Result
949 0 : readUnsignedNumberMaxDigits(int maxDigits,
950 : const ::rtl::OUString & rString, sal_Int32 & io_rnPos,
951 : sal_Int32 & o_rNumber)
952 : {
953 0 : bool bOverflow(false);
954 0 : sal_Int64 nTemp(0);
955 0 : sal_Int32 nPos(io_rnPos);
956 : OSL_ENSURE(maxDigits >= 0, "negative amount of digits makes no sense");
957 :
958 0 : while (nPos < rString.getLength())
959 : {
960 0 : const sal_Unicode c = rString[nPos];
961 0 : if (('0' <= c) && (c <= '9'))
962 : {
963 0 : if (maxDigits > 0)
964 : {
965 0 : nTemp *= 10;
966 0 : nTemp += (c - sal_Unicode('0'));
967 0 : if (nTemp >= SAL_MAX_INT32)
968 : {
969 0 : bOverflow = true;
970 : }
971 0 : --maxDigits;
972 : }
973 : }
974 : else
975 : {
976 : break;
977 : }
978 0 : ++nPos;
979 : }
980 :
981 0 : if (io_rnPos == nPos) // read something?
982 : {
983 0 : o_rNumber = -1;
984 0 : return R_NOTHING;
985 : }
986 :
987 0 : io_rnPos = nPos;
988 0 : o_rNumber = nTemp;
989 0 : return (bOverflow) ? R_OVERFLOW : R_SUCCESS;
990 : }
991 :
992 : static bool
993 0 : readDurationT(const OUString & rString, sal_Int32 & io_rnPos)
994 : {
995 0 : if ((io_rnPos < rString.getLength()) &&
996 0 : (rString[io_rnPos] == 'T'))
997 : {
998 0 : ++io_rnPos;
999 0 : return true;
1000 : }
1001 0 : return false;
1002 : }
1003 :
1004 : static bool
1005 0 : readDurationComponent(const OUString & rString,
1006 : sal_Int32 & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart,
1007 : sal_Int32 & o_rnTarget, const sal_Unicode c)
1008 : {
1009 0 : if ((io_rnPos < rString.getLength()))
1010 : {
1011 0 : if (c == rString[io_rnPos])
1012 : {
1013 0 : ++io_rnPos;
1014 0 : if (-1 != io_rnTemp)
1015 : {
1016 0 : o_rnTarget = io_rnTemp;
1017 0 : io_rnTemp = -1;
1018 0 : if (!io_rbTimePart)
1019 : {
1020 0 : io_rbTimePart = readDurationT(rString, io_rnPos);
1021 : }
1022 : return (R_OVERFLOW !=
1023 0 : readUnsignedNumber(rString, io_rnPos, io_rnTemp));
1024 : }
1025 : else
1026 : {
1027 0 : return false;
1028 : }
1029 : }
1030 : }
1031 0 : return true;
1032 : }
1033 :
1034 : /** convert ISO8601 "duration" string to util::Duration */
1035 0 : bool Converter::convertDuration(util::Duration& rDuration,
1036 : const OUString& rString)
1037 : {
1038 0 : const OUString string = rString.trim().toAsciiUpperCase();
1039 0 : sal_Int32 nPos(0);
1040 :
1041 0 : bool bIsNegativeDuration(false);
1042 0 : if (!string.isEmpty() && ('-' == string[0]))
1043 : {
1044 0 : bIsNegativeDuration = true;
1045 0 : ++nPos;
1046 : }
1047 :
1048 0 : if ((nPos < string.getLength())
1049 0 : && (string[nPos] != 'P')) // duration must start with "P"
1050 : {
1051 0 : return false;
1052 : }
1053 :
1054 0 : ++nPos;
1055 :
1056 : /// last read number; -1 == no valid number! always reset after using!
1057 0 : sal_Int32 nTemp(-1);
1058 0 : bool bTimePart(false); // have we read 'T'?
1059 0 : bool bSuccess(false);
1060 0 : sal_Int32 nYears(0);
1061 0 : sal_Int32 nMonths(0);
1062 0 : sal_Int32 nDays(0);
1063 0 : sal_Int32 nHours(0);
1064 0 : sal_Int32 nMinutes(0);
1065 0 : sal_Int32 nSeconds(0);
1066 0 : sal_Int32 nNanoSeconds(0);
1067 :
1068 0 : bTimePart = readDurationT(string, nPos);
1069 0 : bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1070 :
1071 0 : if (!bTimePart && bSuccess)
1072 : {
1073 : bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1074 0 : nYears, 'Y');
1075 : }
1076 :
1077 0 : if (!bTimePart && bSuccess)
1078 : {
1079 : bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1080 0 : nMonths, 'M');
1081 : }
1082 :
1083 0 : if (!bTimePart && bSuccess)
1084 : {
1085 : bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1086 0 : nDays, 'D');
1087 : }
1088 :
1089 0 : if (bTimePart)
1090 : {
1091 0 : if (-1 == nTemp) // a 'T' must be followed by a component
1092 : {
1093 0 : bSuccess = false;
1094 : }
1095 :
1096 0 : if (bSuccess)
1097 : {
1098 : bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1099 0 : nHours, 'H');
1100 : }
1101 :
1102 0 : if (bSuccess)
1103 : {
1104 : bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1105 0 : nMinutes, 'M');
1106 : }
1107 :
1108 : // eeek! seconds are icky.
1109 0 : if ((nPos < string.getLength()) && bSuccess)
1110 : {
1111 0 : if (string[nPos] == '.' ||
1112 0 : string[nPos] == ',')
1113 : {
1114 0 : ++nPos;
1115 0 : if (-1 != nTemp)
1116 : {
1117 0 : nSeconds = nTemp;
1118 0 : nTemp = -1;
1119 0 : const sal_Int32 nStart(nPos);
1120 0 : bSuccess = readUnsignedNumberMaxDigits(9, string, nPos, nTemp) == R_SUCCESS;
1121 0 : if ((nPos < string.getLength()) && bSuccess)
1122 : {
1123 0 : if (-1 != nTemp)
1124 : {
1125 0 : nNanoSeconds = nTemp;
1126 0 : sal_Int32 nDigits = nPos - nStart;
1127 : assert(nDigits >= 0);
1128 0 : for (; nDigits < 9; ++nDigits)
1129 : {
1130 0 : nNanoSeconds *= 10;
1131 : }
1132 0 : nTemp=-1;
1133 0 : if ('S' == string[nPos])
1134 : {
1135 0 : ++nPos;
1136 : }
1137 : else
1138 : {
1139 0 : bSuccess = false;
1140 : }
1141 : }
1142 : else
1143 : {
1144 0 : bSuccess = false;
1145 : }
1146 : }
1147 : }
1148 : else
1149 : {
1150 0 : bSuccess = false;
1151 : }
1152 : }
1153 0 : else if ('S' == string[nPos])
1154 : {
1155 0 : ++nPos;
1156 0 : if (-1 != nTemp)
1157 : {
1158 0 : nSeconds = nTemp;
1159 0 : nTemp = -1;
1160 : }
1161 : else
1162 : {
1163 0 : bSuccess = false;
1164 : }
1165 : }
1166 : }
1167 : }
1168 :
1169 0 : if (nPos != string.getLength()) // string not processed completely?
1170 : {
1171 0 : bSuccess = false;
1172 : }
1173 :
1174 0 : if (nTemp != -1) // unprocessed number?
1175 : {
1176 0 : bSuccess = false;
1177 : }
1178 :
1179 0 : if (bSuccess)
1180 : {
1181 0 : rDuration.Negative = bIsNegativeDuration;
1182 0 : rDuration.Years = static_cast<sal_Int16>(nYears);
1183 0 : rDuration.Months = static_cast<sal_Int16>(nMonths);
1184 0 : rDuration.Days = static_cast<sal_Int16>(nDays);
1185 0 : rDuration.Hours = static_cast<sal_Int16>(nHours);
1186 0 : rDuration.Minutes = static_cast<sal_Int16>(nMinutes);
1187 0 : rDuration.Seconds = static_cast<sal_Int16>(nSeconds);
1188 0 : rDuration.NanoSeconds = static_cast<sal_Int32>(nNanoSeconds);
1189 : }
1190 :
1191 0 : return bSuccess;
1192 : }
1193 :
1194 :
1195 : static void
1196 0 : lcl_AppendTimezone(OUStringBuffer & i_rBuffer, sal_Int16 const nOffset)
1197 : {
1198 0 : if (0 == nOffset)
1199 : {
1200 0 : i_rBuffer.append('Z');
1201 : }
1202 : else
1203 : {
1204 0 : if (0 < nOffset)
1205 : {
1206 0 : i_rBuffer.append('+');
1207 : }
1208 : else
1209 : {
1210 0 : i_rBuffer.append('-');
1211 : }
1212 0 : const sal_Int32 nHours (abs(nOffset) / 60);
1213 0 : const sal_Int32 nMinutes(abs(nOffset) % 60);
1214 : SAL_WARN_IF(nHours > 14 || (nHours == 14 && nMinutes > 0),
1215 : "sax", "convertDateTime: timezone overflow");
1216 0 : if (nHours < 10)
1217 : {
1218 0 : i_rBuffer.append('0');
1219 : }
1220 0 : i_rBuffer.append(nHours);
1221 0 : i_rBuffer.append(':');
1222 0 : if (nMinutes < 10)
1223 : {
1224 0 : i_rBuffer.append('0');
1225 : }
1226 0 : i_rBuffer.append(nMinutes);
1227 : }
1228 0 : }
1229 :
1230 : /** convert util::Date to ISO "date" string */
1231 0 : void Converter::convertDate(
1232 : OUStringBuffer& i_rBuffer,
1233 : const util::Date& i_rDate,
1234 : sal_Int16 const*const pTimeZoneOffset)
1235 : {
1236 : const util::DateTime dt(0, 0, 0, 0,
1237 0 : i_rDate.Day, i_rDate.Month, i_rDate.Year, false);
1238 0 : convertDateTime(i_rBuffer, dt, pTimeZoneOffset, false);
1239 0 : }
1240 :
1241 0 : static void convertTime(
1242 : OUStringBuffer& i_rBuffer,
1243 : const com::sun::star::util::DateTime& i_rDateTime)
1244 : {
1245 0 : if (i_rDateTime.Hours < 10) {
1246 0 : i_rBuffer.append('0');
1247 : }
1248 0 : i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) )
1249 0 : .append(':');
1250 0 : if (i_rDateTime.Minutes < 10) {
1251 0 : i_rBuffer.append('0');
1252 : }
1253 0 : i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) )
1254 0 : .append(':');
1255 0 : if (i_rDateTime.Seconds < 10) {
1256 0 : i_rBuffer.append('0');
1257 : }
1258 0 : i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1259 0 : if (i_rDateTime.NanoSeconds > 0) {
1260 : OSL_ENSURE(i_rDateTime.NanoSeconds < 1000000000,"NanoSeconds cannot be more than 999 999 999");
1261 0 : i_rBuffer.append('.');
1262 0 : std::ostringstream ostr;
1263 0 : ostr.fill('0');
1264 0 : ostr.width(9);
1265 0 : ostr << i_rDateTime.NanoSeconds;
1266 0 : i_rBuffer.append(OUString::createFromAscii(ostr.str().c_str()));
1267 : }
1268 0 : }
1269 :
1270 0 : static void convertTimeZone(
1271 : OUStringBuffer& i_rBuffer,
1272 : const com::sun::star::util::DateTime& i_rDateTime,
1273 : sal_Int16 const* pTimeZoneOffset)
1274 : {
1275 0 : if (pTimeZoneOffset)
1276 : {
1277 0 : lcl_AppendTimezone(i_rBuffer, *pTimeZoneOffset);
1278 : }
1279 0 : else if (i_rDateTime.IsUTC)
1280 : {
1281 0 : lcl_AppendTimezone(i_rBuffer, 0);
1282 : }
1283 0 : }
1284 :
1285 : /** convert util::DateTime to ISO "time" or "dateTime" string */
1286 0 : void Converter::convertTimeOrDateTime(
1287 : OUStringBuffer& i_rBuffer,
1288 : const com::sun::star::util::DateTime& i_rDateTime,
1289 : sal_Int16 const* pTimeZoneOffset)
1290 : {
1291 0 : if (i_rDateTime.Year == 0 ||
1292 0 : i_rDateTime.Month < 1 || i_rDateTime.Month > 12 ||
1293 0 : i_rDateTime.Day < 1 || i_rDateTime.Day > 31)
1294 : {
1295 0 : convertTime(i_rBuffer, i_rDateTime);
1296 0 : convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1297 : }
1298 : else
1299 : {
1300 0 : convertDateTime(i_rBuffer, i_rDateTime, pTimeZoneOffset, true);
1301 : }
1302 0 : }
1303 :
1304 : /** convert util::DateTime to ISO "date" or "dateTime" string */
1305 0 : void Converter::convertDateTime(
1306 : OUStringBuffer& i_rBuffer,
1307 : const com::sun::star::util::DateTime& i_rDateTime,
1308 : sal_Int16 const*const pTimeZoneOffset,
1309 : bool i_bAddTimeIf0AM )
1310 : {
1311 0 : const sal_Unicode dash('-');
1312 0 : const sal_Unicode zero('0');
1313 :
1314 0 : sal_Int32 const nYear(abs(i_rDateTime.Year));
1315 0 : if (i_rDateTime.Year < 0) {
1316 0 : i_rBuffer.append(dash); // negative
1317 : }
1318 0 : if (nYear < 1000) {
1319 0 : i_rBuffer.append(zero);
1320 : }
1321 0 : if (nYear < 100) {
1322 0 : i_rBuffer.append(zero);
1323 : }
1324 0 : if (nYear < 10) {
1325 0 : i_rBuffer.append(zero);
1326 : }
1327 0 : i_rBuffer.append(nYear).append(dash);
1328 0 : if( i_rDateTime.Month < 10 ) {
1329 0 : i_rBuffer.append(zero);
1330 : }
1331 0 : i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Month) ).append(dash);
1332 0 : if( i_rDateTime.Day < 10 ) {
1333 0 : i_rBuffer.append(zero);
1334 : }
1335 0 : i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day) );
1336 :
1337 0 : if( i_rDateTime.Seconds != 0 ||
1338 0 : i_rDateTime.Minutes != 0 ||
1339 0 : i_rDateTime.Hours != 0 ||
1340 : i_bAddTimeIf0AM )
1341 : {
1342 0 : i_rBuffer.append('T');
1343 0 : convertTime(i_rBuffer, i_rDateTime);
1344 : }
1345 :
1346 0 : convertTimeZone(i_rBuffer, i_rDateTime, pTimeZoneOffset);
1347 0 : }
1348 :
1349 : /** convert ISO "date" or "dateTime" string to util::DateTime */
1350 0 : bool Converter::parseDateTime( util::DateTime& rDateTime,
1351 : boost::optional<sal_Int16> *const pTimeZoneOffset,
1352 : const OUString& rString )
1353 : {
1354 : bool isDateTime;
1355 : return parseDateOrDateTime(0, rDateTime, isDateTime, pTimeZoneOffset,
1356 0 : rString);
1357 : }
1358 :
1359 0 : static bool lcl_isLeapYear(const sal_uInt32 nYear)
1360 : {
1361 0 : return ((nYear % 4) == 0)
1362 0 : && (((nYear % 100) != 0) || ((nYear % 400) == 0));
1363 : }
1364 :
1365 : static sal_uInt16
1366 0 : lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear)
1367 : {
1368 : static const sal_uInt16 s_MaxDaysPerMonth[12] =
1369 : { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1370 : assert(0 < nMonth && nMonth <= 12);
1371 0 : if ((2 == nMonth) && lcl_isLeapYear(nYear))
1372 : {
1373 0 : return 29;
1374 : }
1375 0 : return s_MaxDaysPerMonth[nMonth - 1];
1376 : }
1377 :
1378 0 : static void lcl_ConvertToUTC(
1379 : sal_Int16 & o_rYear, sal_uInt16 & o_rMonth, sal_uInt16 & o_rDay,
1380 : sal_uInt16 & o_rHours, sal_uInt16 & o_rMinutes,
1381 : sal_Int16 const nSourceOffset)
1382 : {
1383 0 : sal_Int16 nOffsetHours(abs(nSourceOffset) / 60);
1384 0 : sal_Int16 const nOffsetMinutes(abs(nSourceOffset) % 60);
1385 0 : o_rMinutes += nOffsetMinutes;
1386 0 : if (nSourceOffset < 0)
1387 : {
1388 0 : o_rMinutes += nOffsetMinutes;
1389 0 : if (60 <= o_rMinutes)
1390 : {
1391 0 : o_rMinutes -= 60;
1392 0 : ++nOffsetHours;
1393 : }
1394 0 : o_rHours += nOffsetHours;
1395 0 : if (o_rHours < 24)
1396 : {
1397 0 : return;
1398 : }
1399 0 : sal_Int16 nDayAdd(0);
1400 0 : while (24 <= o_rHours)
1401 : {
1402 0 : o_rHours -= 24;
1403 0 : ++nDayAdd;
1404 : }
1405 0 : if (o_rDay == 0)
1406 : {
1407 0 : return; // handle time without date - don't adjust what isn't there
1408 : }
1409 0 : o_rDay += nDayAdd;
1410 0 : sal_Int16 const nDaysInMonth(lcl_MaxDaysPerMonth(o_rMonth, o_rYear));
1411 0 : if (o_rDay <= nDaysInMonth)
1412 : {
1413 0 : return;
1414 : }
1415 0 : o_rDay -= nDaysInMonth;
1416 0 : ++o_rMonth;
1417 0 : if (o_rMonth <= 12)
1418 : {
1419 0 : return;
1420 : }
1421 0 : o_rMonth = 1;
1422 0 : ++o_rYear; // works for negative year too
1423 : }
1424 0 : else if (0 < nSourceOffset)
1425 : {
1426 : // argh everything is unsigned
1427 0 : if (o_rMinutes < nOffsetMinutes)
1428 : {
1429 0 : o_rMinutes += 60;
1430 0 : ++nOffsetHours;
1431 : }
1432 0 : o_rMinutes -= nOffsetMinutes;
1433 0 : sal_Int16 nDaySubtract(0);
1434 0 : while (o_rHours < nOffsetHours)
1435 : {
1436 0 : o_rHours += 24;
1437 0 : ++nDaySubtract;
1438 : }
1439 0 : o_rHours -= nOffsetHours;
1440 0 : if (o_rDay == 0)
1441 : {
1442 0 : return; // handle time without date - don't adjust what isn't there
1443 : }
1444 0 : if (nDaySubtract < o_rDay)
1445 : {
1446 0 : o_rDay -= nDaySubtract;
1447 0 : return;
1448 : }
1449 0 : sal_Int16 const nPrevMonth((o_rMonth == 1) ? 12 : o_rMonth - 1);
1450 0 : sal_Int16 const nDaysInMonth(lcl_MaxDaysPerMonth(nPrevMonth, o_rYear));
1451 0 : o_rDay += nDaysInMonth;
1452 0 : --o_rMonth;
1453 0 : if (0 == o_rMonth)
1454 : {
1455 0 : o_rMonth = 12;
1456 0 : --o_rYear; // works for negative year too
1457 : }
1458 0 : o_rDay -= nDaySubtract;
1459 : }
1460 : }
1461 :
1462 : static bool
1463 0 : readDateTimeComponent(const OUString & rString,
1464 : sal_Int32 & io_rnPos, sal_Int32 & o_rnTarget,
1465 : const sal_Int32 nMinLength, const bool bExactLength)
1466 : {
1467 0 : const sal_Int32 nOldPos(io_rnPos);
1468 0 : sal_Int32 nTemp(0);
1469 0 : if (R_SUCCESS != readUnsignedNumber(rString, io_rnPos, nTemp))
1470 : {
1471 0 : return false;
1472 : }
1473 0 : const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1474 0 : if ((nTokenLength < nMinLength) ||
1475 0 : (bExactLength && (nTokenLength > nMinLength)))
1476 : {
1477 0 : return false; // bad length
1478 : }
1479 0 : o_rnTarget = nTemp;
1480 0 : return true;
1481 : }
1482 :
1483 : /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1484 0 : static bool lcl_parseDate(
1485 : bool & isNegative,
1486 : sal_Int32 & nYear, sal_Int32 & nMonth, sal_Int32 & nDay,
1487 : bool & bHaveTime,
1488 : sal_Int32 & nPos,
1489 : const OUString & string,
1490 : bool const bIgnoreInvalidOrMissingDate)
1491 : {
1492 0 : bool bSuccess = true;
1493 :
1494 0 : if (string.getLength() > nPos)
1495 : {
1496 0 : if ('-' == string[nPos])
1497 : {
1498 0 : isNegative = true;
1499 0 : ++nPos;
1500 : }
1501 : }
1502 :
1503 : {
1504 : // While W3C XMLSchema specifies years with a minimum of 4 digits, be
1505 : // leninent in what we accept for years < 1000. One digit is acceptable
1506 : // if the remainders match.
1507 0 : bSuccess = readDateTimeComponent(string, nPos, nYear, 1, false);
1508 0 : if (!bIgnoreInvalidOrMissingDate)
1509 : {
1510 0 : bSuccess &= (0 < nYear);
1511 : }
1512 0 : bSuccess &= (nPos < string.getLength()); // not last token
1513 : }
1514 0 : if (bSuccess && ('-' != string[nPos])) // separator
1515 : {
1516 0 : bSuccess = false;
1517 : }
1518 0 : if (bSuccess)
1519 : {
1520 0 : ++nPos;
1521 : }
1522 :
1523 0 : if (bSuccess)
1524 : {
1525 0 : bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true);
1526 0 : if (!bIgnoreInvalidOrMissingDate)
1527 : {
1528 0 : bSuccess &= (0 < nMonth);
1529 : }
1530 0 : bSuccess &= (nMonth <= 12);
1531 0 : bSuccess &= (nPos < string.getLength()); // not last token
1532 : }
1533 0 : if (bSuccess && ('-' != string[nPos])) // separator
1534 : {
1535 0 : bSuccess = false;
1536 : }
1537 0 : if (bSuccess)
1538 : {
1539 0 : ++nPos;
1540 : }
1541 :
1542 0 : if (bSuccess)
1543 : {
1544 0 : bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1545 0 : if (!bIgnoreInvalidOrMissingDate)
1546 : {
1547 0 : bSuccess &= (0 < nDay);
1548 : }
1549 0 : if (nMonth > 0) // not possible to check if month was missing
1550 : {
1551 0 : bSuccess &= (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear));
1552 : }
1553 : else assert(bIgnoreInvalidOrMissingDate);
1554 : }
1555 :
1556 0 : if (bSuccess && (nPos < string.getLength()))
1557 : {
1558 0 : if ('T' == string[nPos]) // time separator
1559 : {
1560 0 : bHaveTime = true;
1561 0 : ++nPos;
1562 : }
1563 : }
1564 :
1565 0 : return bSuccess;
1566 : }
1567 :
1568 : /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1569 0 : static bool lcl_parseDateTime(
1570 : util::Date *const pDate, util::DateTime & rDateTime,
1571 : bool & rbDateTime,
1572 : boost::optional<sal_Int16> *const pTimeZoneOffset,
1573 : const OUString & rString,
1574 : bool const bIgnoreInvalidOrMissingDate)
1575 : {
1576 0 : bool bSuccess = true;
1577 :
1578 0 : const OUString string = rString.trim().toAsciiUpperCase();
1579 :
1580 0 : bool isNegative(false);
1581 0 : sal_Int32 nYear(0);
1582 0 : sal_Int32 nMonth(0);
1583 0 : sal_Int32 nDay(0);
1584 0 : sal_Int32 nPos(0);
1585 0 : bool bHaveTime(false);
1586 :
1587 0 : if ( !bIgnoreInvalidOrMissingDate
1588 0 : || string.indexOf(':') == -1 // no time?
1589 0 : || (string.indexOf('-') != -1
1590 0 : && string.indexOf('-') < string.indexOf(':')))
1591 : {
1592 : bSuccess &= lcl_parseDate(isNegative, nYear, nMonth, nDay,
1593 0 : bHaveTime, nPos, string, bIgnoreInvalidOrMissingDate);
1594 : }
1595 : else
1596 : {
1597 0 : bHaveTime = true;
1598 : }
1599 :
1600 0 : sal_Int32 nHours(0);
1601 0 : sal_Int32 nMinutes(0);
1602 0 : sal_Int32 nSeconds(0);
1603 0 : sal_Int32 nNanoSeconds(0);
1604 0 : if (bSuccess && bHaveTime)
1605 : {
1606 : {
1607 0 : bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1608 0 : bSuccess &= (0 <= nHours) && (nHours <= 24);
1609 0 : bSuccess &= (nPos < string.getLength()); // not last token
1610 : }
1611 0 : if (bSuccess && (':' != string[nPos])) // separator
1612 : {
1613 0 : bSuccess = false;
1614 : }
1615 0 : if (bSuccess)
1616 : {
1617 0 : ++nPos;
1618 : }
1619 :
1620 0 : if (bSuccess)
1621 : {
1622 0 : bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
1623 0 : bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
1624 0 : bSuccess &= (nPos < string.getLength()); // not last token
1625 : }
1626 0 : if (bSuccess && (':' != string[nPos])) // separator
1627 : {
1628 0 : bSuccess = false;
1629 : }
1630 0 : if (bSuccess)
1631 : {
1632 0 : ++nPos;
1633 : }
1634 :
1635 0 : if (bSuccess)
1636 : {
1637 0 : bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
1638 0 : bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
1639 : }
1640 0 : if (bSuccess && (nPos < string.getLength()) &&
1641 0 : ('.' == string[nPos] || ',' == string[nPos])) // fraction separator
1642 : {
1643 0 : ++nPos;
1644 0 : const sal_Int32 nStart(nPos);
1645 0 : sal_Int32 nTemp(0);
1646 0 : if (R_NOTHING == readUnsignedNumberMaxDigits(9, string, nPos, nTemp))
1647 : {
1648 0 : bSuccess = false;
1649 : }
1650 0 : if (bSuccess)
1651 : {
1652 0 : sal_Int32 nDigits = std::min<sal_Int32>(nPos - nStart, 9);
1653 : assert(nDigits > 0);
1654 0 : for (; nDigits < 9; ++nDigits)
1655 : {
1656 0 : nTemp *= 10;
1657 : }
1658 0 : nNanoSeconds = nTemp;
1659 : }
1660 : }
1661 :
1662 0 : if (bSuccess && (nHours == 24))
1663 : {
1664 0 : if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nNanoSeconds)))
1665 : {
1666 0 : bSuccess = false; // only 24:00:00 is valid
1667 : }
1668 : }
1669 : }
1670 :
1671 0 : bool bHaveTimezone(false);
1672 0 : bool bHaveTimezonePlus(false);
1673 0 : bool bHaveTimezoneMinus(false);
1674 0 : if (bSuccess && (nPos < string.getLength()))
1675 : {
1676 0 : const sal_Unicode c(string[nPos]);
1677 0 : if ('+' == c)
1678 : {
1679 0 : bHaveTimezone = true;
1680 0 : bHaveTimezonePlus = true;
1681 0 : ++nPos;
1682 : }
1683 0 : else if ('-' == c)
1684 : {
1685 0 : bHaveTimezone = true;
1686 0 : bHaveTimezoneMinus = true;
1687 0 : ++nPos;
1688 : }
1689 0 : else if ('Z' == c)
1690 : {
1691 0 : bHaveTimezone = true;
1692 0 : ++nPos;
1693 : }
1694 : else
1695 : {
1696 0 : bSuccess = false;
1697 : }
1698 : }
1699 0 : sal_Int32 nTimezoneHours(0);
1700 0 : sal_Int32 nTimezoneMinutes(0);
1701 0 : if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
1702 : {
1703 : bSuccess = readDateTimeComponent(
1704 0 : string, nPos, nTimezoneHours, 2, true);
1705 0 : bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
1706 0 : bSuccess &= (nPos < string.getLength()); // not last token
1707 0 : if (bSuccess && (':' != string[nPos])) // separator
1708 : {
1709 0 : bSuccess = false;
1710 : }
1711 0 : if (bSuccess)
1712 : {
1713 0 : ++nPos;
1714 : }
1715 0 : if (bSuccess)
1716 : {
1717 : bSuccess = readDateTimeComponent(
1718 0 : string, nPos, nTimezoneMinutes, 2, true);
1719 0 : bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
1720 : }
1721 0 : if (bSuccess && (nTimezoneHours == 14))
1722 : {
1723 0 : if (0 != nTimezoneMinutes)
1724 : {
1725 0 : bSuccess = false; // only +-14:00 is valid
1726 : }
1727 : }
1728 : }
1729 :
1730 0 : bSuccess &= (nPos == string.getLength()); // trailing junk?
1731 :
1732 0 : if (bSuccess)
1733 : {
1734 : sal_Int16 const nTimezoneOffset = ((bHaveTimezoneMinus) ? (-1) : (+1))
1735 0 : * ((nTimezoneHours * 60) + nTimezoneMinutes);
1736 0 : if (!pDate || bHaveTime) // time is optional
1737 : {
1738 : rDateTime.Year =
1739 0 : ((isNegative) ? (-1) : (+1)) * static_cast<sal_Int16>(nYear);
1740 0 : rDateTime.Month = static_cast<sal_uInt16>(nMonth);
1741 0 : rDateTime.Day = static_cast<sal_uInt16>(nDay);
1742 0 : rDateTime.Hours = static_cast<sal_uInt16>(nHours);
1743 0 : rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
1744 0 : rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
1745 0 : rDateTime.NanoSeconds = static_cast<sal_uInt32>(nNanoSeconds);
1746 0 : if (bHaveTimezone)
1747 : {
1748 0 : if (pTimeZoneOffset)
1749 : {
1750 0 : *pTimeZoneOffset = nTimezoneOffset;
1751 0 : rDateTime.IsUTC = (0 == nTimezoneOffset);
1752 : }
1753 : else
1754 : {
1755 : lcl_ConvertToUTC(rDateTime.Year, rDateTime.Month,
1756 : rDateTime.Day, rDateTime.Hours, rDateTime.Minutes,
1757 0 : nTimezoneOffset);
1758 0 : rDateTime.IsUTC = true;
1759 : }
1760 : }
1761 : else
1762 : {
1763 0 : if (pTimeZoneOffset)
1764 : {
1765 0 : pTimeZoneOffset->reset();
1766 : }
1767 0 : rDateTime.IsUTC = false;
1768 : }
1769 0 : rbDateTime = bHaveTime;
1770 : }
1771 : else
1772 : {
1773 : pDate->Year =
1774 0 : ((isNegative) ? (-1) : (+1)) * static_cast<sal_Int16>(nYear);
1775 0 : pDate->Month = static_cast<sal_uInt16>(nMonth);
1776 0 : pDate->Day = static_cast<sal_uInt16>(nDay);
1777 0 : if (bHaveTimezone)
1778 : {
1779 0 : if (pTimeZoneOffset)
1780 : {
1781 0 : *pTimeZoneOffset = nTimezoneOffset;
1782 : }
1783 : else
1784 : {
1785 : // a Date cannot be adjusted
1786 : SAL_INFO("sax", "dropping timezone");
1787 : }
1788 : }
1789 : else
1790 : {
1791 0 : if (pTimeZoneOffset)
1792 : {
1793 0 : pTimeZoneOffset->reset();
1794 : }
1795 : }
1796 0 : rbDateTime = false;
1797 : }
1798 : }
1799 0 : return bSuccess;
1800 : }
1801 :
1802 : /** convert ISO "time" or "dateTime" string to util::DateTime */
1803 0 : bool Converter::parseTimeOrDateTime(
1804 : util::DateTime & rDateTime,
1805 : boost::optional<sal_Int16> * pTimeZoneOffset,
1806 : const OUString & rString)
1807 : {
1808 : bool dummy;
1809 : return lcl_parseDateTime(
1810 0 : 0, rDateTime, dummy, pTimeZoneOffset, rString, true);
1811 : }
1812 :
1813 : /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1814 0 : bool Converter::parseDateOrDateTime(
1815 : util::Date *const pDate, util::DateTime & rDateTime,
1816 : bool & rbDateTime,
1817 : boost::optional<sal_Int16> *const pTimeZoneOffset,
1818 : const OUString & rString )
1819 : {
1820 : return lcl_parseDateTime(
1821 0 : pDate, rDateTime, rbDateTime, pTimeZoneOffset, rString, false);
1822 : }
1823 :
1824 :
1825 : /** gets the position of the first comma after npos in the string
1826 : rStr. Commas inside '"' pairs are not matched */
1827 0 : sal_Int32 Converter::indexOfComma( const OUString& rStr,
1828 : sal_Int32 nPos )
1829 : {
1830 0 : sal_Unicode cQuote = 0;
1831 0 : sal_Int32 nLen = rStr.getLength();
1832 0 : for( ; nPos < nLen; nPos++ )
1833 : {
1834 0 : sal_Unicode c = rStr[nPos];
1835 0 : switch( c )
1836 : {
1837 : case sal_Unicode('\''):
1838 0 : if( 0 == cQuote )
1839 0 : cQuote = c;
1840 0 : else if( '\'' == cQuote )
1841 0 : cQuote = 0;
1842 0 : break;
1843 :
1844 : case sal_Unicode('"'):
1845 0 : if( 0 == cQuote )
1846 0 : cQuote = c;
1847 0 : else if( '\"' == cQuote )
1848 0 : cQuote = 0;
1849 0 : break;
1850 :
1851 : case sal_Unicode(','):
1852 0 : if( 0 == cQuote )
1853 0 : return nPos;
1854 0 : break;
1855 : }
1856 : }
1857 :
1858 0 : return -1;
1859 : }
1860 :
1861 : const
1862 : sal_Char aBase64EncodeTable[] =
1863 : { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1864 : 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1865 : 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1866 : 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1867 : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1868 :
1869 : const
1870 : sal_uInt8 aBase64DecodeTable[] =
1871 : { 62,255,255,255, 63, // 43-47
1872 : // + /
1873 :
1874 : 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
1875 : // 0 1 2 3 4 5 6 7 8 9 =
1876 :
1877 : 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
1878 : // A B C D E F G H I J K L M N O
1879 :
1880 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1881 : // P Q R S T U V W X Y Z
1882 :
1883 : 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1884 : // a b c d e f g h i j k l m n o
1885 :
1886 : 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1887 : // p q r s t u v w x y z
1888 :
1889 :
1890 :
1891 0 : void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, OUStringBuffer& sBuffer)
1892 : {
1893 0 : sal_Int32 nLen(nFullLen - nStart);
1894 0 : if (nLen > 3)
1895 0 : nLen = 3;
1896 0 : if (nLen == 0)
1897 : {
1898 0 : return;
1899 : }
1900 :
1901 : sal_Int32 nBinaer;
1902 0 : switch (nLen)
1903 : {
1904 : case 1:
1905 : {
1906 0 : nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
1907 : }
1908 0 : break;
1909 : case 2:
1910 : {
1911 0 : nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1912 0 : (((sal_uInt8)pBuffer[nStart + 1]) << 8);
1913 : }
1914 0 : break;
1915 : default:
1916 : {
1917 0 : nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1918 0 : (((sal_uInt8)pBuffer[nStart + 1]) << 8) +
1919 0 : ((sal_uInt8)pBuffer[nStart + 2]);
1920 : }
1921 0 : break;
1922 : }
1923 :
1924 0 : sal_Unicode buf[] = { '=', '=', '=', '=' };
1925 :
1926 0 : sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
1927 0 : buf[0] = aBase64EncodeTable [nIndex];
1928 :
1929 0 : nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
1930 0 : buf[1] = aBase64EncodeTable [nIndex];
1931 0 : if (nLen > 1)
1932 : {
1933 0 : nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
1934 0 : buf[2] = aBase64EncodeTable [nIndex];
1935 0 : if (nLen > 2)
1936 : {
1937 0 : nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
1938 0 : buf[3] = aBase64EncodeTable [nIndex];
1939 : }
1940 : }
1941 0 : sBuffer.append(buf, SAL_N_ELEMENTS(buf));
1942 : }
1943 :
1944 0 : void Converter::encodeBase64(OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
1945 : {
1946 0 : sal_Int32 i(0);
1947 0 : sal_Int32 nBufferLength(aPass.getLength());
1948 0 : const sal_Int8* pBuffer = aPass.getConstArray();
1949 0 : while (i < nBufferLength)
1950 : {
1951 0 : ThreeByteToFourByte (pBuffer, i, nBufferLength, aStrBuffer);
1952 0 : i += 3;
1953 : }
1954 0 : }
1955 :
1956 0 : void Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const OUString& sBuffer)
1957 : {
1958 : #if OSL_DEBUG_LEVEL > 0
1959 : sal_Int32 nCharsDecoded =
1960 : #endif
1961 0 : decodeBase64SomeChars( aBuffer, sBuffer );
1962 : OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" );
1963 0 : }
1964 :
1965 0 : sal_Int32 Converter::decodeBase64SomeChars(
1966 : uno::Sequence<sal_Int8>& rOutBuffer,
1967 : const OUString& rInBuffer)
1968 : {
1969 0 : sal_Int32 nInBufferLen = rInBuffer.getLength();
1970 0 : sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
1971 0 : if( rOutBuffer.getLength() < nMinOutBufferLen )
1972 0 : rOutBuffer.realloc( nMinOutBufferLen );
1973 :
1974 0 : const sal_Unicode *pInBuffer = rInBuffer.getStr();
1975 0 : sal_Int8 *pOutBuffer = rOutBuffer.getArray();
1976 0 : sal_Int8 *pOutBufferStart = pOutBuffer;
1977 0 : sal_Int32 nCharsDecoded = 0;
1978 :
1979 : sal_uInt8 aDecodeBuffer[4];
1980 0 : sal_Int32 nBytesToDecode = 0;
1981 0 : sal_Int32 nBytesGotFromDecoding = 3;
1982 0 : sal_Int32 nInBufferPos= 0;
1983 0 : while( nInBufferPos < nInBufferLen )
1984 : {
1985 0 : sal_Unicode cChar = *pInBuffer;
1986 0 : if( cChar >= '+' && cChar <= 'z' )
1987 : {
1988 0 : sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
1989 0 : if( nByte != 255 )
1990 : {
1991 : // We have found a valid character!
1992 0 : aDecodeBuffer[nBytesToDecode++] = nByte;
1993 :
1994 : // One '=' character at the end means 2 out bytes
1995 : // Two '=' characters at the end mean 1 out bytes
1996 0 : if( '=' == cChar && nBytesToDecode > 2 )
1997 0 : nBytesGotFromDecoding--;
1998 0 : if( 4 == nBytesToDecode )
1999 : {
2000 : // Four characters found, so we may convert now!
2001 0 : sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
2002 0 : (aDecodeBuffer[1] << 12) +
2003 0 : (aDecodeBuffer[2] << 6) +
2004 0 : aDecodeBuffer[3];
2005 :
2006 0 : *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16);
2007 0 : if( nBytesGotFromDecoding > 1 )
2008 0 : *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8);
2009 0 : if( nBytesGotFromDecoding > 2 )
2010 0 : *pOutBuffer++ = (sal_Int8)(nOut & 0xff);
2011 0 : nCharsDecoded = nInBufferPos + 1;
2012 0 : nBytesToDecode = 0;
2013 0 : nBytesGotFromDecoding = 3;
2014 : }
2015 : }
2016 : else
2017 : {
2018 0 : nCharsDecoded++;
2019 0 : }
2020 : }
2021 : else
2022 : {
2023 0 : nCharsDecoded++;
2024 : }
2025 :
2026 0 : nInBufferPos++;
2027 0 : pInBuffer++;
2028 : }
2029 0 : if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
2030 0 : rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
2031 :
2032 0 : return nCharsDecoded;
2033 : }
2034 :
2035 0 : double Converter::GetConversionFactor(OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
2036 : {
2037 0 : double fRetval(1.0);
2038 0 : rUnit.setLength(0L);
2039 :
2040 0 : const sal_Char* psUnit = 0;
2041 :
2042 0 : if(nSourceUnit != nTargetUnit)
2043 : {
2044 0 : switch(nSourceUnit)
2045 : {
2046 : case MeasureUnit::TWIP:
2047 : {
2048 0 : switch(nTargetUnit)
2049 : {
2050 : case MeasureUnit::MM_100TH:
2051 : {
2052 : // 0.01mm = 0.57twip (exactly)
2053 0 : fRetval = ((25400.0 / 1440.0) / 10.0);
2054 0 : break;
2055 : }
2056 : case MeasureUnit::MM_10TH:
2057 : {
2058 : // 0.01mm = 0.57twip (exactly)
2059 0 : fRetval = ((25400.0 / 1440.0) / 100.0);
2060 0 : break;
2061 : }
2062 : case MeasureUnit::MM:
2063 : {
2064 : // 0.01mm = 0.57twip (exactly)
2065 0 : fRetval = ((25400.0 / 1440.0) / 1000.0);
2066 0 : psUnit = gpsMM;
2067 0 : break;
2068 : }
2069 : case MeasureUnit::CM:
2070 : {
2071 : // 0.001cm = 0.57twip (exactly)
2072 0 : fRetval = ((25400.0 / 1440.0) / 10000.0);
2073 0 : psUnit = gpsCM;
2074 0 : break;
2075 : }
2076 : case MeasureUnit::POINT:
2077 : {
2078 : // 0.01pt = 0.2twip (exactly)
2079 0 : fRetval = ((1000.0 / 20.0) / 1000.0);
2080 0 : psUnit = gpsPT;
2081 0 : break;
2082 : }
2083 : case MeasureUnit::INCH:
2084 : default:
2085 : {
2086 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
2087 : // 0.0001in = 0.144twip (exactly)
2088 0 : fRetval = ((100000.0 / 1440.0) / 100000.0);
2089 0 : psUnit = gpsINCH;
2090 0 : break;
2091 : }
2092 : }
2093 0 : break;
2094 : }
2095 : case MeasureUnit::POINT:
2096 : {
2097 0 : switch(nTargetUnit)
2098 : {
2099 : case MeasureUnit::MM_100TH:
2100 : {
2101 : // 1mm = 72 / 25.4 pt (exactly)
2102 0 : fRetval = ( 2540.0 / 72.0 );
2103 0 : break;
2104 : }
2105 : case MeasureUnit::MM_10TH:
2106 : {
2107 : // 1mm = 72 / 25.4 pt (exactly)
2108 0 : fRetval = ( 254.0 / 72.0 );
2109 0 : break;
2110 : }
2111 : case MeasureUnit::MM:
2112 : {
2113 : // 1mm = 72 / 25.4 pt (exactly)
2114 0 : fRetval = ( 25.4 / 72.0 );
2115 0 : psUnit = gpsMM;
2116 0 : break;
2117 :
2118 : }
2119 : case MeasureUnit::CM:
2120 : {
2121 : // 1cm = 72 / 2.54 pt (exactly)
2122 0 : fRetval = ( 2.54 / 72.0 );
2123 0 : psUnit = gpsCM;
2124 0 : break;
2125 : }
2126 : case MeasureUnit::TWIP:
2127 : {
2128 : // 1twip = 72 / 1440 pt (exactly)
2129 0 : fRetval = 20.0; // 1440.0 / 72.0
2130 0 : psUnit = gpsPC;
2131 0 : break;
2132 : }
2133 : case MeasureUnit::INCH:
2134 : default:
2135 : {
2136 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values");
2137 : // 1in = 72 pt (exactly)
2138 0 : fRetval = ( 1.0 / 72.0 );
2139 0 : psUnit = gpsINCH;
2140 0 : break;
2141 : }
2142 : }
2143 0 : break;
2144 : }
2145 : case MeasureUnit::MM_10TH:
2146 : {
2147 0 : switch(nTargetUnit)
2148 : {
2149 : case MeasureUnit::MM_100TH:
2150 : {
2151 0 : fRetval = 10.0;
2152 0 : break;
2153 : }
2154 : case MeasureUnit::MM:
2155 : {
2156 : // 0.01mm = 1 mm/100 (exactly)
2157 0 : fRetval = ((10.0 / 1.0) / 100.0);
2158 0 : psUnit = gpsMM;
2159 0 : break;
2160 : }
2161 : case MeasureUnit::CM:
2162 : {
2163 0 : fRetval = ((10.0 / 1.0) / 1000.0);
2164 0 : psUnit = gpsCM;
2165 0 : break;
2166 : }
2167 : case MeasureUnit::POINT:
2168 : {
2169 : // 0.01pt = 0.35 mm/100 (exactly)
2170 0 : fRetval = ((72000.0 / 2540.0) / 100.0);
2171 0 : psUnit = gpsPT;
2172 0 : break;
2173 : }
2174 : case MeasureUnit::TWIP:
2175 : {
2176 0 : fRetval = ((20.0 * 72000.0 / 2540.0) / 100.0);
2177 0 : psUnit = gpsPC;
2178 0 : break;
2179 : }
2180 : case MeasureUnit::INCH:
2181 : default:
2182 : {
2183 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/10mm values");
2184 : // 0.0001in = 0.254 mm/100 (exactly)
2185 0 : fRetval = ((100000.0 / 2540.0) / 10000.0);
2186 0 : psUnit = gpsINCH;
2187 0 : break;
2188 : }
2189 : }
2190 0 : break;
2191 : }
2192 : case MeasureUnit::MM_100TH:
2193 : {
2194 0 : switch(nTargetUnit)
2195 : {
2196 : case MeasureUnit::MM_10TH:
2197 : {
2198 0 : fRetval = ((10.0 / 1.0) / 100.0);
2199 0 : break;
2200 : }
2201 : case MeasureUnit::MM:
2202 : {
2203 : // 0.01mm = 1 mm/100 (exactly)
2204 0 : fRetval = ((10.0 / 1.0) / 1000.0);
2205 0 : psUnit = gpsMM;
2206 0 : break;
2207 : }
2208 : case MeasureUnit::CM:
2209 : {
2210 0 : fRetval = ((10.0 / 1.0) / 10000.0);
2211 0 : psUnit = gpsCM;
2212 0 : break;
2213 : }
2214 : case MeasureUnit::POINT:
2215 : {
2216 : // 0.01pt = 0.35 mm/100 (exactly)
2217 0 : fRetval = ((72000.0 / 2540.0) / 1000.0);
2218 0 : psUnit = gpsPT;
2219 0 : break;
2220 : }
2221 : case MeasureUnit::TWIP:
2222 : {
2223 0 : fRetval = ((20.0 * 72000.0 / 2540.0) / 1000.0);
2224 0 : psUnit = gpsPC;
2225 0 : break;
2226 : }
2227 : case MeasureUnit::INCH:
2228 : default:
2229 : {
2230 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
2231 : // 0.0001in = 0.254 mm/100 (exactly)
2232 0 : fRetval = ((100000.0 / 2540.0) / 100000.0);
2233 0 : psUnit = gpsINCH;
2234 0 : break;
2235 : }
2236 : }
2237 0 : break;
2238 : }
2239 : case MeasureUnit::MM:
2240 : {
2241 0 : switch(nTargetUnit)
2242 : {
2243 : case MeasureUnit::MM_100TH:
2244 : {
2245 0 : fRetval = 100.0;
2246 0 : break;
2247 : }
2248 : case MeasureUnit::MM_10TH:
2249 : {
2250 0 : fRetval = 10.0;
2251 0 : break;
2252 : }
2253 : case MeasureUnit::CM:
2254 : {
2255 0 : fRetval = 0.1;
2256 0 : psUnit = gpsCM;
2257 0 : break;
2258 : }
2259 : case MeasureUnit::POINT:
2260 : {
2261 0 : fRetval = 72.0 / (2.54 * 10);
2262 0 : psUnit = gpsPT;
2263 0 : break;
2264 : }
2265 : case MeasureUnit::TWIP:
2266 : {
2267 0 : fRetval = (20.0 * 72.0) / (2.54 * 10);
2268 0 : psUnit = gpsPC;
2269 0 : break;
2270 : }
2271 : case MeasureUnit::INCH:
2272 : default:
2273 : {
2274 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for cm values");
2275 0 : fRetval = 1 / (2.54 * 10);
2276 0 : psUnit = gpsINCH;
2277 0 : break;
2278 : }
2279 : }
2280 0 : break;
2281 : }
2282 : case MeasureUnit::CM:
2283 : {
2284 0 : switch(nTargetUnit)
2285 : {
2286 : case MeasureUnit::MM_100TH:
2287 : {
2288 0 : fRetval = 1000.0;
2289 0 : break;
2290 : }
2291 : case MeasureUnit::MM_10TH:
2292 : {
2293 0 : fRetval = 100.0;
2294 0 : break;
2295 : }
2296 : case MeasureUnit::MM:
2297 : {
2298 0 : fRetval = 10.0;
2299 0 : psUnit = gpsMM;
2300 0 : break;
2301 : }
2302 : case MeasureUnit::CM:
2303 : {
2304 0 : break;
2305 : }
2306 : case MeasureUnit::POINT:
2307 : {
2308 0 : fRetval = 72.0 / 2.54;
2309 0 : psUnit = gpsPT;
2310 0 : break;
2311 : }
2312 : case MeasureUnit::TWIP:
2313 : {
2314 0 : fRetval = (20.0 * 72.0) / 2.54;
2315 0 : psUnit = gpsPC;
2316 0 : break;
2317 : }
2318 : case MeasureUnit::INCH:
2319 : default:
2320 : {
2321 : OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for cm values");
2322 0 : fRetval = 1 / 2.54;
2323 0 : psUnit = gpsINCH;
2324 0 : break;
2325 : }
2326 : }
2327 0 : break;
2328 : }
2329 : case MeasureUnit::INCH:
2330 : {
2331 0 : switch (nTargetUnit)
2332 : {
2333 : case MeasureUnit::MM_100TH:
2334 : {
2335 0 : fRetval = 2540;
2336 0 : break;
2337 : }
2338 : case MeasureUnit::MM_10TH:
2339 : {
2340 0 : fRetval = 254;
2341 0 : break;
2342 : }
2343 : case MeasureUnit::MM:
2344 : {
2345 0 : fRetval = 25.4;
2346 0 : psUnit = gpsMM;
2347 0 : break;
2348 : }
2349 : case MeasureUnit::CM:
2350 : {
2351 0 : fRetval = 2.54;
2352 0 : psUnit = gpsCM;
2353 0 : break;
2354 : }
2355 : case MeasureUnit::POINT:
2356 : {
2357 0 : fRetval = 72.0;
2358 0 : psUnit = gpsPT;
2359 0 : break;
2360 : }
2361 : case MeasureUnit::TWIP:
2362 : {
2363 0 : fRetval = 72.0 * 20.0;
2364 0 : psUnit = gpsPC;
2365 0 : break;
2366 : }
2367 : default:
2368 : {
2369 : OSL_FAIL("output unit not supported for in values");
2370 0 : fRetval = 1;
2371 0 : psUnit = gpsINCH;
2372 0 : break;
2373 : }
2374 : }
2375 0 : break;
2376 : }
2377 : default:
2378 : OSL_ENSURE(false, "sax::Converter::GetConversionFactor(): "
2379 : "source unit not supported");
2380 0 : break;
2381 : }
2382 :
2383 0 : if( psUnit )
2384 0 : rUnit.appendAscii( psUnit );
2385 : }
2386 :
2387 0 : return fRetval;
2388 : }
2389 :
2390 0 : sal_Int16 Converter::GetUnitFromString(const OUString& rString, sal_Int16 nDefaultUnit)
2391 : {
2392 0 : sal_Int32 nPos = 0L;
2393 0 : sal_Int32 nLen = rString.getLength();
2394 0 : sal_Int16 nRetUnit = nDefaultUnit;
2395 :
2396 : // skip white space
2397 0 : while( nPos < nLen && ' ' == rString[nPos] )
2398 0 : nPos++;
2399 :
2400 : // skip negative
2401 0 : if( nPos < nLen && '-' == rString[nPos] )
2402 0 : nPos++;
2403 :
2404 : // skip number
2405 0 : while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2406 0 : nPos++;
2407 :
2408 0 : if( nPos < nLen && '.' == rString[nPos] )
2409 : {
2410 0 : nPos++;
2411 0 : while( nPos < nLen && '0' <= rString[nPos] && '9' >= rString[nPos] )
2412 0 : nPos++;
2413 : }
2414 :
2415 : // skip white space
2416 0 : while( nPos < nLen && ' ' == rString[nPos] )
2417 0 : nPos++;
2418 :
2419 0 : if( nPos < nLen )
2420 : {
2421 0 : switch(rString[nPos])
2422 : {
2423 : case sal_Unicode('%') :
2424 : {
2425 0 : nRetUnit = MeasureUnit::PERCENT;
2426 0 : break;
2427 : }
2428 : case sal_Unicode('c'):
2429 : case sal_Unicode('C'):
2430 : {
2431 0 : if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2432 0 : || rString[nPos+1] == 'M'))
2433 0 : nRetUnit = MeasureUnit::CM;
2434 0 : break;
2435 : }
2436 : case sal_Unicode('e'):
2437 : case sal_Unicode('E'):
2438 : {
2439 : // CSS1_EMS or CSS1_EMX later
2440 0 : break;
2441 : }
2442 : case sal_Unicode('i'):
2443 : case sal_Unicode('I'):
2444 : {
2445 0 : if(nPos+1 < nLen && (rString[nPos+1] == 'n'
2446 0 : || rString[nPos+1] == 'N'))
2447 0 : nRetUnit = MeasureUnit::INCH;
2448 0 : break;
2449 : }
2450 : case sal_Unicode('m'):
2451 : case sal_Unicode('M'):
2452 : {
2453 0 : if(nPos+1 < nLen && (rString[nPos+1] == 'm'
2454 0 : || rString[nPos+1] == 'M'))
2455 0 : nRetUnit = MeasureUnit::MM;
2456 0 : break;
2457 : }
2458 : case sal_Unicode('p'):
2459 : case sal_Unicode('P'):
2460 : {
2461 0 : if(nPos+1 < nLen && (rString[nPos+1] == 't'
2462 0 : || rString[nPos+1] == 'T'))
2463 0 : nRetUnit = MeasureUnit::POINT;
2464 0 : if(nPos+1 < nLen && (rString[nPos+1] == 'c'
2465 0 : || rString[nPos+1] == 'C'))
2466 0 : nRetUnit = MeasureUnit::TWIP;
2467 0 : break;
2468 : }
2469 : }
2470 : }
2471 :
2472 0 : return nRetUnit;
2473 : }
2474 :
2475 :
2476 0 : bool Converter::convertAny(OUStringBuffer& rsValue,
2477 : OUStringBuffer& rsType ,
2478 : const com::sun::star::uno::Any& rValue)
2479 : {
2480 0 : bool bConverted = false;
2481 :
2482 0 : rsValue.setLength(0);
2483 0 : rsType.setLength (0);
2484 :
2485 0 : switch (rValue.getValueTypeClass())
2486 : {
2487 : case com::sun::star::uno::TypeClass_BYTE :
2488 : case com::sun::star::uno::TypeClass_SHORT :
2489 : case com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
2490 : case com::sun::star::uno::TypeClass_LONG :
2491 : case com::sun::star::uno::TypeClass_UNSIGNED_LONG :
2492 : {
2493 0 : sal_Int32 nTempValue = 0;
2494 0 : if (rValue >>= nTempValue)
2495 : {
2496 0 : rsType.appendAscii("integer");
2497 0 : bConverted = true;
2498 0 : ::sax::Converter::convertNumber(rsValue, nTempValue);
2499 : }
2500 : }
2501 0 : break;
2502 :
2503 : case com::sun::star::uno::TypeClass_BOOLEAN :
2504 : {
2505 0 : bool bTempValue = false;
2506 0 : if (rValue >>= bTempValue)
2507 : {
2508 0 : rsType.appendAscii("boolean");
2509 0 : bConverted = true;
2510 0 : ::sax::Converter::convertBool(rsValue, bTempValue);
2511 : }
2512 : }
2513 0 : break;
2514 :
2515 : case com::sun::star::uno::TypeClass_FLOAT :
2516 : case com::sun::star::uno::TypeClass_DOUBLE :
2517 : {
2518 0 : double fTempValue = 0.0;
2519 0 : if (rValue >>= fTempValue)
2520 : {
2521 0 : rsType.appendAscii("float");
2522 0 : bConverted = true;
2523 0 : ::sax::Converter::convertDouble(rsValue, fTempValue);
2524 : }
2525 : }
2526 0 : break;
2527 :
2528 : case com::sun::star::uno::TypeClass_STRING :
2529 : {
2530 0 : OUString sTempValue;
2531 0 : if (rValue >>= sTempValue)
2532 : {
2533 0 : rsType.appendAscii("string");
2534 0 : bConverted = true;
2535 0 : rsValue.append(sTempValue);
2536 0 : }
2537 : }
2538 0 : break;
2539 :
2540 : case com::sun::star::uno::TypeClass_STRUCT :
2541 : {
2542 0 : com::sun::star::util::Date aDate ;
2543 0 : com::sun::star::util::Time aTime ;
2544 0 : com::sun::star::util::DateTime aDateTime;
2545 :
2546 0 : if (rValue >>= aDate)
2547 : {
2548 0 : rsType.appendAscii("date");
2549 0 : bConverted = true;
2550 0 : com::sun::star::util::DateTime aTempValue;
2551 0 : aTempValue.Day = aDate.Day;
2552 0 : aTempValue.Month = aDate.Month;
2553 0 : aTempValue.Year = aDate.Year;
2554 0 : aTempValue.NanoSeconds = 0;
2555 0 : aTempValue.Seconds = 0;
2556 0 : aTempValue.Minutes = 0;
2557 0 : aTempValue.Hours = 0;
2558 0 : ::sax::Converter::convertDateTime(rsValue, aTempValue, 0);
2559 : }
2560 : else
2561 0 : if (rValue >>= aTime)
2562 : {
2563 0 : rsType.appendAscii("time");
2564 0 : bConverted = true;
2565 0 : com::sun::star::util::Duration aTempValue;
2566 0 : aTempValue.Days = 0;
2567 0 : aTempValue.Months = 0;
2568 0 : aTempValue.Years = 0;
2569 0 : aTempValue.NanoSeconds = aTime.NanoSeconds;
2570 0 : aTempValue.Seconds = aTime.Seconds;
2571 0 : aTempValue.Minutes = aTime.Minutes;
2572 0 : aTempValue.Hours = aTime.Hours;
2573 0 : ::sax::Converter::convertDuration(rsValue, aTempValue);
2574 : }
2575 : else
2576 0 : if (rValue >>= aDateTime)
2577 : {
2578 0 : rsType.appendAscii("date");
2579 0 : bConverted = true;
2580 0 : ::sax::Converter::convertDateTime(rsValue, aDateTime, 0);
2581 : }
2582 : }
2583 0 : break;
2584 : default:
2585 0 : break;
2586 : }
2587 :
2588 0 : return bConverted;
2589 : }
2590 :
2591 : }
2592 :
2593 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|