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