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