1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: converter.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include <com/sun/star/i18n/UnicodeType.hpp>
33 #include <com/sun/star/util/DateTime.hpp>
34 #include <com/sun/star/util/Date.hpp>
35 #include <com/sun/star/util/Time.hpp>
36 #include <com/sun/star/uno/Sequence.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <rtl/math.hxx>
39 #include "sax/tools/converter.hxx"
42 using namespace com::sun::star
;
43 using namespace com::sun::star::uno
;
44 using namespace com::sun::star::util
;
45 //using namespace com::sun::star::text;
46 //using namespace com::sun::star::style;
47 using namespace ::com::sun::star::i18n
;
51 static const sal_Char
* gpsMM
= "mm";
52 static const sal_Char
* gpsCM
= "cm";
53 static const sal_Char
* gpsPT
= "pt";
54 static const sal_Char
* gpsINCH
= "in";
55 static const sal_Char
* gpsPC
= "pc";
57 const sal_Int8 XML_MAXDIGITSCOUNT_TIME
= 11;
58 const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME
= 6;
59 #define XML_NULLDATE "NullDate"
61 /** convert string to measure using optional min and max values*/
62 bool Converter::convertMeasure( sal_Int32
& rValue
,
63 const OUString
& rString
,
64 sal_Int16 nTargetUnit
/* = MeasureUnit::MM_100TH */,
65 sal_Int32 nMin
/* = SAL_MIN_INT32 */,
66 sal_Int32 nMax
/* = SAL_MAX_INT32 */ )
72 sal_Int32 nLen
= rString
.getLength();
75 while( (nPos
< nLen
) && (rString
[nPos
] <= sal_Unicode(' ')) )
78 if( nPos
< nLen
&& sal_Unicode('-') == rString
[nPos
] )
86 sal_Unicode('0') <= rString
[nPos
] &&
87 sal_Unicode('9') >= rString
[nPos
] )
89 // TODO: check overflow!
91 nVal
+= (rString
[nPos
] - sal_Unicode('0'));
95 if( nPos
< nLen
&& sal_Unicode('.') == rString
[nPos
] )
100 sal_Unicode('0') <= rString
[nPos
] &&
101 sal_Unicode('9') >= rString
[nPos
] )
103 // TODO: check overflow!
105 nVal
+= ( ((double)(rString
[nPos
] - sal_Unicode('0'))) / nDiv
);
111 while( (nPos
< nLen
) && (rString
[nPos
] <= sal_Unicode(' ')) )
117 if( MeasureUnit::PERCENT
== nTargetUnit
)
119 if( sal_Unicode('%') != rString
[nPos
] )
122 else if( MeasureUnit::PIXEL
== nTargetUnit
)
124 if( nPos
+ 1 >= nLen
||
125 (sal_Unicode('p') != rString
[nPos
] &&
126 sal_Unicode('P') != rString
[nPos
])||
127 (sal_Unicode('x') != rString
[nPos
+1] &&
128 sal_Unicode('X') != rString
[nPos
+1]) )
133 OSL_ENSURE( MeasureUnit::TWIP
== nTargetUnit
|| MeasureUnit::POINT
== nTargetUnit
||
134 MeasureUnit::MM_100TH
== nTargetUnit
|| MeasureUnit::MM_10TH
== nTargetUnit
, "unit is not supported");
135 const sal_Char
*aCmpsL
[2] = { 0, 0 };
136 const sal_Char
*aCmpsU
[2] = { 0, 0 };
137 double aScales
[2] = { 1., 1. };
139 if( MeasureUnit::TWIP
== nTargetUnit
)
141 switch( rString
[nPos
] )
143 case sal_Unicode('c'):
144 case sal_Unicode('C'):
147 aScales
[0] = (72.*20.)/2.54; // twip
149 case sal_Unicode('i'):
150 case sal_Unicode('I'):
153 aScales
[0] = 72.*20.; // twip
155 case sal_Unicode('m'):
156 case sal_Unicode('M'):
159 aScales
[0] = (72.*20.)/25.4; // twip
161 case sal_Unicode('p'):
162 case sal_Unicode('P'):
165 aScales
[0] = 20.; // twip
169 aScales
[1] = 12.*20.; // twip
173 else if( MeasureUnit::MM_100TH
== nTargetUnit
|| MeasureUnit::MM_10TH
== nTargetUnit
)
175 double nScaleFactor
= (MeasureUnit::MM_100TH
== nTargetUnit
) ? 100.0 : 10.0;
176 switch( rString
[nPos
] )
178 case sal_Unicode('c'):
179 case sal_Unicode('C'):
182 aScales
[0] = 10.0 * nScaleFactor
; // mm/100
184 case sal_Unicode('i'):
185 case sal_Unicode('I'):
188 aScales
[0] = 1000.*2.54; // mm/100
190 case sal_Unicode('m'):
191 case sal_Unicode('M'):
194 aScales
[0] = 1.0 * nScaleFactor
; // mm/100
196 case sal_Unicode('p'):
197 case sal_Unicode('P'):
200 aScales
[0] = (10.0 * nScaleFactor
*2.54)/72.; // mm/100
204 aScales
[1] = (10.0 * nScaleFactor
*2.54)/12.; // mm/100
208 else if( MeasureUnit::POINT
== nTargetUnit
)
210 if( rString
[nPos
] == 'p' || rString
[nPos
] == 'P' )
218 if( aCmpsL
[0] == NULL
)
222 for( sal_uInt16 i
= 0; i
< 2; i
++ )
224 const sal_Char
*pL
= aCmpsL
[i
];
227 const sal_Char
*pU
= aCmpsU
[i
];
228 while( nPos
< nLen
&& *pL
)
230 sal_Unicode c
= rString
[nPos
];
231 if( c
!= *pL
&& c
!= *pU
)
237 if( !*pL
&& (nPos
== nLen
|| ' ' == rString
[nPos
]) )
248 // TODO: check overflow
258 if( nVal
<= (double)nMin
)
260 else if( nVal
>= (double)nMax
)
263 rValue
= (sal_Int32
)nVal
;
268 /** convert measure in given unit to string with given unit */
269 void Converter::convertMeasure( OUStringBuffer
& rBuffer
,
271 sal_Int16 nSourceUnit
/* = MeasureUnit::MM_100TH */,
272 sal_Int16 nTargetUnit
/* = MeasureUnit::INCH */ )
274 OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" );
280 if( nSourceUnit
== MeasureUnit::PERCENT
)
282 OSL_ENSURE( nTargetUnit
== MeasureUnit::PERCENT
,
283 "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
285 rBuffer
.append( nMeasure
);
286 rBuffer
.append( sal_Unicode('%' ) );
290 // the sign is processed seperatly
293 nMeasure
= -nMeasure
;
294 rBuffer
.append( sal_Unicode('-') );
297 // The new length is (nVal * nMul)/(nDiv*nFac*10)
301 const sal_Char
* psUnit
= 0;
302 switch( nSourceUnit
)
304 case MeasureUnit::TWIP
:
305 switch( nTargetUnit
)
307 case MeasureUnit::MM_100TH
:
308 case MeasureUnit::MM_10TH
:
309 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
,"output unit not supported for twip values" );
310 case MeasureUnit::MM
:
311 // 0.01mm = 0.57twip (exactly)
312 nMul
= 25400; // 25.4 * 1000
313 nDiv
= 1440; // 72 * 20;
318 case MeasureUnit::CM
:
319 // 0.001cm = 0.57twip (exactly)
320 nMul
= 25400; // 2.54 * 10000
321 nDiv
= 1440; // 72 * 20;
326 case MeasureUnit::POINT
:
327 // 0.01pt = 0.2twip (exactly)
334 case MeasureUnit::INCH
:
336 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
,
337 "output unit not supported for twip values" );
338 // 0.0001in = 0.144twip (exactly)
340 nDiv
= 1440; // 72 * 20;
347 case MeasureUnit::POINT
:
348 // 1pt = 1pt (exactly)
349 OSL_ENSURE( MeasureUnit::POINT
== nTargetUnit
,
350 "output unit not supported for pt values" );
356 case MeasureUnit::MM_10TH
:
357 case MeasureUnit::MM_100TH
:
359 long nFac2
= (MeasureUnit::MM_100TH
== nSourceUnit
) ? 100 : 10;
360 switch( nTargetUnit
)
362 case MeasureUnit::MM_100TH
:
363 case MeasureUnit::MM_10TH
:
364 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
,
365 "output unit not supported for 1/100mm values" );
366 case MeasureUnit::MM
:
367 // 0.01mm = 1 mm/100 (exactly)
374 case MeasureUnit::CM
:
375 // 0.001mm = 1 mm/100 (exactly)
377 nDiv
= 1; // 72 * 20;
382 case MeasureUnit::POINT
:
383 // 0.01pt = 0.35 mm/100 (exactly)
390 case MeasureUnit::INCH
:
392 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
,
393 "output unit not supported for 1/100mm values" );
394 // 0.0001in = 0.254 mm/100 (exactly)
406 bool bOutLongVal
= true;
407 if( nMeasure
> SAL_INT32_MAX
/ nMul
)
409 // A big int is required for calculation
410 BigInt
nBigVal( nMeasure
);
411 BigInt
nBigFac( nFac
);
417 if( nBigVal
.IsLong() )
419 // To convert the value into a string a long is sufficient
420 nLongVal
= (long)nBigVal
;
424 BigInt
nBigFac2( nFac
);
426 rBuffer
.append( (sal_Int32
)(nBigVal
/ nBigFac2
) );
427 if( !(nBigVal
% nBigFac2
).IsZero() )
429 rBuffer
.append( sal_Unicode('.') );
430 while( nFac
> 1 && !(nBigVal
% nBigFac2
).IsZero() )
434 rBuffer
.append( (sal_Int32
)((nBigVal
/ nBigFac2
) % nBig10
) );
442 nLongVal
= nMeasure
* nMul
;
450 rBuffer
.append( (sal_Int32
)(nLongVal
/ nFac
) );
451 if( nFac
> 1 && (nLongVal
% nFac
) != 0 )
453 rBuffer
.append( sal_Unicode('.') );
454 while( nFac
> 1 && (nLongVal
% nFac
) != 0 )
457 rBuffer
.append( (sal_Int32
)((nLongVal
/ nFac
) % 10) );
463 rBuffer
.appendAscii( psUnit
);
468 static const OUString
& getTrueString()
470 static const OUString
sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
474 static const OUString
& getFalseString()
476 static const OUString
sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
480 /** convert string to boolean */
481 bool Converter::convertBool( bool& rBool
, const OUString
& rString
)
483 rBool
= rString
== getTrueString();
485 return rBool
|| (rString
== getFalseString());
488 /** convert boolean to string */
489 void Converter::convertBool( OUStringBuffer
& rBuffer
, bool bValue
)
491 rBuffer
.append( bValue
? getTrueString() : getFalseString() );
494 /** convert string to percent */
495 bool Converter::convertPercent( sal_Int32
& rPercent
, const OUString
& rString
)
497 return convertMeasure( rPercent
, rString
, MeasureUnit::PERCENT
);
500 /** convert percent to string */
501 void Converter::convertPercent( OUStringBuffer
& rBuffer
, sal_Int32 nValue
)
503 rBuffer
.append( nValue
);
504 rBuffer
.append( sal_Unicode('%' ) );
507 /** convert string to pixel measure */
508 bool Converter::convertMeasurePx( sal_Int32
& rPixel
, const OUString
& rString
)
510 return convertMeasure( rPixel
, rString
, MeasureUnit::PIXEL
);
513 /** convert pixel measure to string */
514 void Converter::convertMeasurePx( OUStringBuffer
& rBuffer
, sal_Int32 nValue
)
516 rBuffer
.append( nValue
);
517 rBuffer
.append( sal_Unicode('p' ) );
518 rBuffer
.append( sal_Unicode('x' ) );
521 int lcl_gethex( int nChar
)
523 if( nChar
>= '0' && nChar
<= '9' )
525 else if( nChar
>= 'a' && nChar
<= 'f' )
526 return nChar
- 'a' + 10;
527 else if( nChar
>= 'A' && nChar
<= 'F' )
528 return nChar
- 'A' + 10;
533 /** convert string to color */
534 bool Converter::convertColor( sal_Int32
& rColor
, const OUString
& rValue
)
536 if( rValue
.getLength() != 7 || rValue
[0] != '#' )
539 rColor
= lcl_gethex( rValue
[1] ) * 16 + lcl_gethex( rValue
[2] );
542 rColor
|= ( lcl_gethex( rValue
[3] ) * 16 + lcl_gethex( rValue
[4] ) );
545 rColor
|= ( lcl_gethex( rValue
[5] ) * 16 + lcl_gethex( rValue
[6] ) );
550 static sal_Char aHexTab
[] = "0123456789abcdef";
552 /** convert color to string */
553 void Converter::convertColor( OUStringBuffer
& rBuffer
, sal_Int32 nColor
)
555 rBuffer
.append( sal_Unicode( '#' ) );
557 sal_uInt8 nCol
= (sal_uInt8
)(nColor
>> 16);
558 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
>> 4 ] ) );
559 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
& 0xf ] ) );
561 nCol
= (sal_uInt8
)(nColor
>> 8);
562 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
>> 4 ] ) );
563 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
& 0xf ] ) );
565 nCol
= (sal_uInt8
)nColor
;
566 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
>> 4 ] ) );
567 rBuffer
.append( sal_Unicode( aHexTab
[ nCol
& 0xf ] ) );
570 /** convert number to string */
571 void Converter::convertNumber( OUStringBuffer
& rBuffer
, sal_Int32 nNumber
)
573 rBuffer
.append( nNumber
);
576 /** convert string to number with optional min and max values */
577 bool Converter::convertNumber( sal_Int32
& rValue
,
578 const OUString
& rString
,
579 sal_Int32 nMin
, sal_Int32 nMax
)
585 sal_Int32 nLen
= rString
.getLength();
588 while( (nPos
< nLen
) && (rString
[nPos
] <= sal_Unicode(' ')) )
591 if( nPos
< nLen
&& sal_Unicode('-') == rString
[nPos
] )
598 while( nPos
< nLen
&&
599 sal_Unicode('0') <= rString
[nPos
] &&
600 sal_Unicode('9') >= rString
[nPos
] )
602 // TODO: check overflow!
604 rValue
+= (rString
[nPos
] - sal_Unicode('0'));
613 else if( rValue
> nMax
)
619 /** convert double number to string (using ::rtl::math) */
620 void Converter::convertDouble( OUStringBuffer
& rBuffer
,
623 sal_Int16 nSourceUnit
,
624 sal_Int16 nTargetUnit
)
626 if(MeasureUnit::PERCENT
== nSourceUnit
)
628 OSL_ENSURE( nTargetUnit
== MeasureUnit::PERCENT
, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
629 ::rtl::math::doubleToUStringBuffer( rBuffer
, fNumber
, rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
, '.', true);
631 rBuffer
.append(sal_Unicode('%'));
635 OUStringBuffer sUnit
;
636 double fFactor
= GetConversionFactor(sUnit
, nSourceUnit
, nTargetUnit
);
639 ::rtl::math::doubleToUStringBuffer( rBuffer
, fNumber
, rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
, '.', true);
641 rBuffer
.append(sUnit
);
645 /** convert double number to string (using ::rtl::math) */
646 void Converter::convertDouble( ::rtl::OUStringBuffer
& rBuffer
, double fNumber
)
648 ::rtl::math::doubleToUStringBuffer( rBuffer
, fNumber
, rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
, '.', true);
651 /** convert string to double number (using ::rtl::math) */
652 bool Converter::convertDouble(double& rValue
,
653 const ::rtl::OUString
& rString
, sal_Int16 nTargetUnit
)
655 sal_Int16 nSourceUnit
= GetUnitFromString(rString
, nTargetUnit
);
657 return convertDouble(rValue
, rString
, nSourceUnit
, nTargetUnit
);
660 /** convert string to double number (using ::rtl::math) */
661 bool Converter::convertDouble(double& rValue
,
662 const ::rtl::OUString
& rString
, sal_Int16 nSourceUnit
, sal_Int16 nTargetUnit
)
664 rtl_math_ConversionStatus eStatus
;
665 rValue
= ::rtl::math::stringToDouble( rString
, (sal_Unicode
)('.'), (sal_Unicode
)(','), &eStatus
, NULL
);
667 if(eStatus
== rtl_math_ConversionStatus_Ok
)
669 OUStringBuffer sUnit
;
670 double fFactor
= GetConversionFactor(sUnit
, nSourceUnit
, nTargetUnit
);
671 if(fFactor
!= 1.0 && fFactor
!= 0.0)
675 return ( eStatus
== rtl_math_ConversionStatus_Ok
);
678 /** convert string to double number (using ::rtl::math) */
679 bool Converter::convertDouble(double& rValue
, const ::rtl::OUString
& rString
)
681 rtl_math_ConversionStatus eStatus
;
682 rValue
= ::rtl::math::stringToDouble( rString
, (sal_Unicode
)('.'), (sal_Unicode
)(','), &eStatus
, NULL
);
683 return ( eStatus
== rtl_math_ConversionStatus_Ok
);
686 /** convert double to ISO Time String; negative durations allowed */
687 void Converter::convertTime( ::rtl::OUStringBuffer
& rBuffer
,
691 double fValue
= fTime
;
693 // take care of negative durations as specified in:
694 // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
697 rBuffer
.append(sal_Unicode('-'));
701 rBuffer
.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
703 double fHoursValue
= ::rtl::math::approxFloor (fValue
);
704 fValue
-= fHoursValue
;
706 double fMinsValue
= ::rtl::math::approxFloor (fValue
);
707 fValue
-= fMinsValue
;
709 double fSecsValue
= ::rtl::math::approxFloor (fValue
);
710 fValue
-= fSecsValue
;
711 double f100SecsValue
;
712 if (fValue
> 0.00001)
713 f100SecsValue
= ::rtl::math::round( fValue
, XML_MAXDIGITSCOUNT_TIME
- 5);
717 if (f100SecsValue
== 1.0)
722 if (fSecsValue
>= 60.0)
727 if (fMinsValue
>= 60.0)
733 if (fHoursValue
< 10)
734 rBuffer
.append( sal_Unicode('0'));
735 rBuffer
.append( sal_Int32( fHoursValue
));
736 rBuffer
.append( sal_Unicode('H'));
738 rBuffer
.append( sal_Unicode('0'));
739 rBuffer
.append( sal_Int32( fMinsValue
));
740 rBuffer
.append( sal_Unicode('M'));
742 rBuffer
.append( sal_Unicode('0'));
743 rBuffer
.append( sal_Int32( fSecsValue
));
744 if (f100SecsValue
> 0.0)
746 ::rtl::OUString
a100th( ::rtl::math::doubleToUString( fValue
,
747 rtl_math_StringFormat_F
, XML_MAXDIGITSCOUNT_TIME
- 5, '.',
749 if ( a100th
.getLength() > 2 )
751 rBuffer
.append( sal_Unicode('.'));
752 rBuffer
.append( a100th
.copy( 2 ) ); // strip 0.
755 rBuffer
.append( sal_Unicode('S'));
758 /** convert ISO Time String to double; negative durations allowed */
759 bool Converter::convertTime( double& fTime
,
760 const ::rtl::OUString
& rString
)
762 rtl::OUString aTrimmed
= rString
.trim().toAsciiUpperCase();
763 const sal_Unicode
* pStr
= aTrimmed
.getStr();
765 // negative time duration?
766 bool bIsNegativeDuration
= false;
767 if ( sal_Unicode('-') == (*pStr
) )
769 bIsNegativeDuration
= true;
773 if ( *(pStr
++) != sal_Unicode('P') ) // duration must start with "P"
776 rtl::OUString sDoubleStr
;
777 bool bSuccess
= true;
779 bool bTimePart
= false;
780 bool bIsFraction
= false;
782 sal_Int32 nHours
= 0;
787 while ( bSuccess
&& !bDone
)
789 sal_Unicode c
= *(pStr
++);
792 else if ( sal_Unicode('0') <= c
&& sal_Unicode('9') >= c
)
794 if ( nTemp
>= SAL_MAX_INT32
/ 10 )
801 nTemp
+= (c
- sal_Unicode('0'));
805 sDoubleStr
+= OUString::valueOf(c
);
809 else if ( bTimePart
)
811 if ( c
== sal_Unicode('H') )
816 else if ( c
== sal_Unicode('M') )
821 else if ( (c
== sal_Unicode(',')) || (c
== sal_Unicode('.')) )
826 sDoubleStr
= OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
828 else if ( c
== sal_Unicode('S') )
834 sDoubleStr
= OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
838 bSuccess
= false; // invalid character
842 if ( c
== sal_Unicode('T') ) // "T" starts time part
844 else if ( c
== sal_Unicode('D') )
849 else if ( c
== sal_Unicode('Y') || c
== sal_Unicode('M') )
851 //! how many days is a year or month?
853 OSL_ENSURE( false, "years or months in duration: not implemented");
857 bSuccess
= false; // invalid character
864 nHours
+= nDays
* 24; // add the days to the hours part
865 double fTempTime
= 0.0;
866 double fHour
= nHours
;
869 double fSec100
= 0.0;
870 double fFraction
= sDoubleStr
.toDouble();
871 fTempTime
= fHour
/ 24;
872 fTempTime
+= fMin
/ (24 * 60);
873 fTempTime
+= fSec
/ (24 * 60 * 60);
874 fTempTime
+= fSec100
/ (24 * 60 * 60 * 60);
875 fTempTime
+= fFraction
/ (24 * 60 * 60);
877 // negative duration?
878 if ( bIsNegativeDuration
)
880 fTempTime
= -fTempTime
;
888 /** convert util::DateTime to ISO Time String */
889 void Converter::convertTime( ::rtl::OUStringBuffer
& rBuffer
,
890 const ::com::sun::star::util::DateTime
& rDateTime
)
892 double fHour
= rDateTime
.Hours
;
893 double fMin
= rDateTime
.Minutes
;
894 double fSec
= rDateTime
.Seconds
;
895 double fSec100
= rDateTime
.HundredthSeconds
;
896 double fTempTime
= fHour
/ 24;
897 fTempTime
+= fMin
/ (24 * 60);
898 fTempTime
+= fSec
/ (24 * 60 * 60);
899 fTempTime
+= fSec100
/ (24 * 60 * 60 * 100);
900 convertTime( rBuffer
, fTempTime
);
903 /** convert ISO Time String to util::DateTime */
904 bool Converter::convertTime( ::com::sun::star::util::DateTime
& rDateTime
,
905 const ::rtl::OUString
& rString
)
907 double fCalculatedTime
= 0.0;
908 if( convertTime( fCalculatedTime
, rString
) )
910 // #101357# declare as volatile to prevent optimization
912 volatile double fTempTime
= fCalculatedTime
;
914 double fHoursValue
= ::rtl::math::approxFloor (fTempTime
);
915 fTempTime
-= fHoursValue
;
917 double fMinsValue
= ::rtl::math::approxFloor (fTempTime
);
918 fTempTime
-= fMinsValue
;
920 double fSecsValue
= ::rtl::math::approxFloor (fTempTime
);
921 fTempTime
-= fSecsValue
;
922 double f100SecsValue
= 0.0;
924 if( fTempTime
> 0.00001 )
925 f100SecsValue
= fTempTime
;
930 rDateTime
.Hours
= static_cast < sal_uInt16
> ( fHoursValue
);
931 rDateTime
.Minutes
= static_cast < sal_uInt16
> ( fMinsValue
);
932 rDateTime
.Seconds
= static_cast < sal_uInt16
> ( fSecsValue
);
933 rDateTime
.HundredthSeconds
= static_cast < sal_uInt16
> ( f100SecsValue
* 100.0 );
940 /** convert util::DateTime to ISO Date String */
941 void Converter::convertDateTime(
942 ::rtl::OUStringBuffer
& i_rBuffer
,
943 const com::sun::star::util::DateTime
& i_rDateTime
,
944 bool i_bAddTimeIf0AM
)
946 const sal_Unicode
dash('-');
947 const sal_Unicode
col (':');
948 const sal_Unicode
dot ('.');
949 const sal_Unicode
zero('0');
950 const sal_Unicode
tee ('T');
952 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Year
) ).append(dash
);
953 if( i_rDateTime
.Month
< 10 ) {
954 i_rBuffer
.append(zero
);
956 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Month
) ).append(dash
);
957 if( i_rDateTime
.Day
< 10 ) {
958 i_rBuffer
.append(zero
);
960 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Day
) );
962 if( i_rDateTime
.Seconds
!= 0 ||
963 i_rDateTime
.Minutes
!= 0 ||
964 i_rDateTime
.Hours
!= 0 ||
967 i_rBuffer
.append(tee
);
968 if( i_rDateTime
.Hours
< 10 ) {
969 i_rBuffer
.append(zero
);
971 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Hours
) )
973 if( i_rDateTime
.Minutes
< 10 ) {
974 i_rBuffer
.append(zero
);
976 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Minutes
) )
978 if( i_rDateTime
.Seconds
< 10 ) {
979 i_rBuffer
.append(zero
);
981 i_rBuffer
.append( static_cast<sal_Int32
>(i_rDateTime
.Seconds
) );
982 if( i_rDateTime
.HundredthSeconds
> 0 ) {
983 i_rBuffer
.append(dot
);
984 if( i_rDateTime
.HundredthSeconds
< 10 ) {
985 i_rBuffer
.append(zero
);
988 static_cast<sal_Int32
>(i_rDateTime
.HundredthSeconds
) );
993 /** convert ISO Date String to util::DateTime */
994 bool Converter::convertDateTime( com::sun::star::util::DateTime
& rDateTime
,
995 const ::rtl::OUString
& rString
)
997 bool bSuccess
= true;
999 rtl::OUString aDateStr
, aTimeStr
, sDoubleStr
;
1000 sal_Int32 nPos
= rString
.indexOf( (sal_Unicode
) 'T' );
1001 sal_Int32 nPos2
= rString
.indexOf( (sal_Unicode
) ',' );
1003 nPos2
= rString
.indexOf( (sal_Unicode
) '.' );
1006 aDateStr
= rString
.copy( 0, nPos
);
1009 aTimeStr
= rString
.copy( nPos
+ 1, nPos2
- nPos
- 1 );
1010 sDoubleStr
= OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
1011 sDoubleStr
+= rString
.copy( nPos2
+ 1 );
1015 aTimeStr
= rString
.copy(nPos
+ 1);
1016 sDoubleStr
= OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
1020 aDateStr
= rString
; // no separator: only date part
1022 sal_Int32 nYear
= 1899;
1023 sal_Int32 nMonth
= 12;
1024 sal_Int32 nDay
= 30;
1025 sal_Int32 nHour
= 0;
1029 const sal_Unicode
* pStr
= aDateStr
.getStr();
1030 sal_Int32 nDateTokens
= 1;
1037 if ( nDateTokens
> 3 || aDateStr
.getLength() == 0 )
1042 if ( !convertNumber( nYear
, aDateStr
.getToken( 0, '-', n
), 0, 9999 ) )
1044 if ( nDateTokens
>= 2 )
1045 if ( !convertNumber( nMonth
, aDateStr
.getToken( 0, '-', n
), 0, 12 ) )
1047 if ( nDateTokens
>= 3 )
1048 if ( !convertNumber( nDay
, aDateStr
.getToken( 0, '-', n
), 0, 31 ) )
1052 if ( aTimeStr
.getLength() > 0 ) // time is optional
1054 pStr
= aTimeStr
.getStr();
1055 sal_Int32 nTimeTokens
= 1;
1062 if ( nTimeTokens
> 3 )
1067 if ( !convertNumber( nHour
, aTimeStr
.getToken( 0, ':', n
), 0, 23 ) )
1069 if ( nTimeTokens
>= 2 )
1070 if ( !convertNumber( nMin
, aTimeStr
.getToken( 0, ':', n
), 0, 59 ) )
1072 if ( nTimeTokens
>= 3 )
1073 if ( !convertNumber( nSec
, aTimeStr
.getToken( 0, ':', n
), 0, 59 ) )
1080 rDateTime
.Year
= (sal_uInt16
)nYear
;
1081 rDateTime
.Month
= (sal_uInt16
)nMonth
;
1082 rDateTime
.Day
= (sal_uInt16
)nDay
;
1083 rDateTime
.Hours
= (sal_uInt16
)nHour
;
1084 rDateTime
.Minutes
= (sal_uInt16
)nMin
;
1085 rDateTime
.Seconds
= (sal_uInt16
)nSec
;
1086 rDateTime
.HundredthSeconds
= (sal_uInt16
)(sDoubleStr
.toDouble() * 100);
1091 /** gets the position of the first comma after npos in the string
1092 rStr. Commas inside '"' pairs are not matched */
1093 sal_Int32
Converter::indexOfComma( const OUString
& rStr
,
1096 sal_Unicode cQuote
= 0;
1097 sal_Int32 nLen
= rStr
.getLength();
1098 for( ; nPos
< nLen
; nPos
++ )
1100 sal_Unicode c
= rStr
[nPos
];
1103 case sal_Unicode('\''):
1106 else if( '\'' == cQuote
)
1110 case sal_Unicode('"'):
1113 else if( '\"' == cQuote
)
1117 case sal_Unicode(','):
1128 sal_Char aBase64EncodeTable
[] =
1129 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1130 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1131 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1132 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1133 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1136 sal_uInt8 aBase64DecodeTable
[] =
1137 { 62,255,255,255, 63, // 43-47
1140 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
1141 // 0 1 2 3 4 5 6 7 8 9 =
1143 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
1144 // A B C D E F G H I J K L M N O
1146 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1147 // P Q R S T U V W X Y Z
1149 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1150 // a b c d e f g h i j k l m n o
1152 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1153 // p q r s t u v w x y z
1157 void ThreeByteToFourByte (const sal_Int8
* pBuffer
, const sal_Int32 nStart
, const sal_Int32 nFullLen
, rtl::OUStringBuffer
& sBuffer
)
1159 sal_Int32
nLen(nFullLen
- nStart
);
1164 sBuffer
.setLength(0);
1173 nBinaer
= ((sal_uInt8
)pBuffer
[nStart
+ 0]) << 16;
1178 nBinaer
= (((sal_uInt8
)pBuffer
[nStart
+ 0]) << 16) +
1179 (((sal_uInt8
)pBuffer
[nStart
+ 1]) << 8);
1184 nBinaer
= (((sal_uInt8
)pBuffer
[nStart
+ 0]) << 16) +
1185 (((sal_uInt8
)pBuffer
[nStart
+ 1]) << 8) +
1186 ((sal_uInt8
)pBuffer
[nStart
+ 2]);
1191 sBuffer
.appendAscii("====");
1193 sal_uInt8
nIndex (static_cast<sal_uInt8
>((nBinaer
& 0xFC0000) >> 18));
1194 sBuffer
.setCharAt(0, aBase64EncodeTable
[nIndex
]);
1196 nIndex
= static_cast<sal_uInt8
>((nBinaer
& 0x3F000) >> 12);
1197 sBuffer
.setCharAt(1, aBase64EncodeTable
[nIndex
]);
1201 nIndex
= static_cast<sal_uInt8
>((nBinaer
& 0xFC0) >> 6);
1202 sBuffer
.setCharAt(2, aBase64EncodeTable
[nIndex
]);
1206 nIndex
= static_cast<sal_uInt8
>((nBinaer
& 0x3F));
1207 sBuffer
.setCharAt(3, aBase64EncodeTable
[nIndex
]);
1210 void Converter::encodeBase64(rtl::OUStringBuffer
& aStrBuffer
, const uno::Sequence
<sal_Int8
>& aPass
)
1213 sal_Int32
nBufferLength(aPass
.getLength());
1214 const sal_Int8
* pBuffer
= aPass
.getConstArray();
1215 while (i
< nBufferLength
)
1217 rtl::OUStringBuffer sBuffer
;
1218 ThreeByteToFourByte (pBuffer
, i
, nBufferLength
, sBuffer
);
1219 aStrBuffer
.append(sBuffer
);
1224 void Converter::decodeBase64(uno::Sequence
<sal_Int8
>& aBuffer
, const rtl::OUString
& sBuffer
)
1226 #if OSL_DEBUG_LEVEL > 0
1227 sal_Int32 nCharsDecoded
=
1229 decodeBase64SomeChars( aBuffer
, sBuffer
);
1230 OSL_ENSURE( nCharsDecoded
== sBuffer
.getLength(), "some bytes left in base64 decoding!" );
1233 sal_Int32
Converter::decodeBase64SomeChars(
1234 uno::Sequence
<sal_Int8
>& rOutBuffer
,
1235 const rtl::OUString
& rInBuffer
)
1237 sal_Int32 nInBufferLen
= rInBuffer
.getLength();
1238 sal_Int32 nMinOutBufferLen
= (nInBufferLen
/ 4) * 3;
1239 if( rOutBuffer
.getLength() < nMinOutBufferLen
)
1240 rOutBuffer
.realloc( nMinOutBufferLen
);
1242 const sal_Unicode
*pInBuffer
= rInBuffer
.getStr();
1243 sal_Int8
*pOutBuffer
= rOutBuffer
.getArray();
1244 sal_Int8
*pOutBufferStart
= pOutBuffer
;
1245 sal_Int32 nCharsDecoded
= 0;
1247 sal_uInt8 aDecodeBuffer
[4];
1248 sal_Int32 nBytesToDecode
= 0;
1249 sal_Int32 nBytesGotFromDecoding
= 3;
1250 sal_Int32 nInBufferPos
= 0;
1251 while( nInBufferPos
< nInBufferLen
)
1253 sal_Unicode cChar
= *pInBuffer
;
1254 if( cChar
>= '+' && cChar
<= 'z' )
1256 sal_uInt8 nByte
= aBase64DecodeTable
[cChar
-'+'];
1259 // We have found a valid character!
1260 aDecodeBuffer
[nBytesToDecode
++] = nByte
;
1262 // One '=' character at the end means 2 out bytes
1263 // Two '=' characters at the end mean 1 out bytes
1264 if( '=' == cChar
&& nBytesToDecode
> 2 )
1265 nBytesGotFromDecoding
--;
1266 if( 4 == nBytesToDecode
)
1268 // Four characters found, so we may convert now!
1269 sal_uInt32 nOut
= (aDecodeBuffer
[0] << 18) +
1270 (aDecodeBuffer
[1] << 12) +
1271 (aDecodeBuffer
[2] << 6) +
1274 *pOutBuffer
++ = (sal_Int8
)((nOut
& 0xff0000) >> 16);
1275 if( nBytesGotFromDecoding
> 1 )
1276 *pOutBuffer
++ = (sal_Int8
)((nOut
& 0xff00) >> 8);
1277 if( nBytesGotFromDecoding
> 2 )
1278 *pOutBuffer
++ = (sal_Int8
)(nOut
& 0xff);
1279 nCharsDecoded
= nInBufferPos
+ 1;
1281 nBytesGotFromDecoding
= 3;
1297 if( (pOutBuffer
- pOutBufferStart
) != rOutBuffer
.getLength() )
1298 rOutBuffer
.realloc( pOutBuffer
- pOutBufferStart
);
1300 return nCharsDecoded
;
1303 void Converter::clearUndefinedChars(rtl::OUString
& rTarget
, const rtl::OUString
& rSource
)
1305 sal_uInt32
nLength(rSource
.getLength());
1306 rtl::OUStringBuffer
sBuffer(nLength
);
1307 for (sal_uInt32 i
= 0; i
< nLength
; i
++)
1309 sal_Unicode cChar
= rSource
[i
];
1310 if (!(cChar
< 0x0020) ||
1311 (cChar
== 0x0009) || // TAB
1312 (cChar
== 0x000A) || // LF
1313 (cChar
== 0x000D)) // legal character
1314 sBuffer
.append(cChar
);
1316 rTarget
= sBuffer
.makeStringAndClear();
1319 double Converter::GetConversionFactor(::rtl::OUStringBuffer
& rUnit
, sal_Int16 nSourceUnit
, sal_Int16 nTargetUnit
)
1321 double fRetval(1.0);
1322 rUnit
.setLength(0L);
1324 const sal_Char
* psUnit
= 0;
1326 if(nSourceUnit
!= nTargetUnit
)
1330 case MeasureUnit::TWIP
:
1334 case MeasureUnit::MM_100TH
:
1335 case MeasureUnit::MM_10TH
:
1337 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for twip values");
1339 case MeasureUnit::MM
:
1341 // 0.01mm = 0.57twip (exactly)
1342 fRetval
= ((25400.0 / 1440.0) / 1000.0);
1346 case MeasureUnit::CM
:
1348 // 0.001cm = 0.57twip (exactly)
1349 fRetval
= ((25400.0 / 1440.0) / 10000.0);
1353 case MeasureUnit::POINT
:
1355 // 0.01pt = 0.2twip (exactly)
1356 fRetval
= ((1000.0 / 20.0) / 1000.0);
1360 case MeasureUnit::INCH
:
1363 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for twip values");
1364 // 0.0001in = 0.144twip (exactly)
1365 fRetval
= ((100000.0 / 1440.0) / 100000.0);
1372 case MeasureUnit::POINT
:
1376 case MeasureUnit::MM
:
1377 // 1mm = 72 / 25.4 pt (exactly)
1378 fRetval
= ( 25.4 / 72.0 );
1382 case MeasureUnit::CM
:
1383 // 1cm = 72 / 2.54 pt (exactly)
1384 fRetval
= ( 2.54 / 72.0 );
1388 case MeasureUnit::TWIP
:
1389 // 1twip = 72 / 1440 pt (exactly)
1390 fRetval
= 20.0; // 1440.0 / 72.0
1394 case MeasureUnit::INCH
:
1396 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for pt values");
1397 // 1in = 72 pt (exactly)
1398 fRetval
= ( 1.0 / 72.0 );
1404 case MeasureUnit::MM_10TH
:
1408 case MeasureUnit::MM_100TH
:
1409 case MeasureUnit::MM_10TH
:
1411 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for 1/100mm values");
1413 case MeasureUnit::MM
:
1415 // 0.01mm = 1 mm/100 (exactly)
1416 fRetval
= ((10.0 / 1.0) / 100.0);
1420 case MeasureUnit::CM
:
1422 // 0.001mm = 1 mm/100 (exactly)
1423 fRetval
= ((10.0 / 1.0) / 1000.0);
1427 case MeasureUnit::POINT
:
1429 // 0.01pt = 0.35 mm/100 (exactly)
1430 fRetval
= ((72000.0 / 2540.0) / 100.0);
1434 case MeasureUnit::INCH
:
1437 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for 1/100mm values");
1438 // 0.0001in = 0.254 mm/100 (exactly)
1439 fRetval
= ((100000.0 / 2540.0) / 10000.0);
1446 case MeasureUnit::MM_100TH
:
1450 case MeasureUnit::MM_100TH
:
1451 case MeasureUnit::MM_10TH
:
1453 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for 1/100mm values");
1455 case MeasureUnit::MM
:
1457 // 0.01mm = 1 mm/100 (exactly)
1458 fRetval
= ((10.0 / 1.0) / 1000.0);
1462 case MeasureUnit::CM
:
1464 // 0.001mm = 1 mm/100 (exactly)
1465 fRetval
= ((10.0 / 1.0) / 10000.0);
1469 case MeasureUnit::POINT
:
1471 // 0.01pt = 0.35 mm/100 (exactly)
1472 fRetval
= ((72000.0 / 2540.0) / 1000.0);
1476 case MeasureUnit::INCH
:
1479 OSL_ENSURE( MeasureUnit::INCH
== nTargetUnit
, "output unit not supported for 1/100mm values");
1480 // 0.0001in = 0.254 mm/100 (exactly)
1481 fRetval
= ((100000.0 / 2540.0) / 100000.0);
1491 rUnit
.appendAscii( psUnit
);
1497 sal_Int16
Converter::GetUnitFromString(const ::rtl::OUString
& rString
, sal_Int16 nDefaultUnit
)
1499 sal_Int32 nPos
= 0L;
1500 sal_Int32 nLen
= rString
.getLength();
1501 sal_Int16 nRetUnit
= nDefaultUnit
;
1504 while( nPos
< nLen
&& sal_Unicode(' ') == rString
[nPos
] )
1508 if( nPos
< nLen
&& sal_Unicode('-') == rString
[nPos
] )
1512 while( nPos
< nLen
&& sal_Unicode('0') <= rString
[nPos
] && sal_Unicode('9') >= rString
[nPos
] )
1515 if( nPos
< nLen
&& sal_Unicode('.') == rString
[nPos
] )
1518 while( nPos
< nLen
&& sal_Unicode('0') <= rString
[nPos
] && sal_Unicode('9') >= rString
[nPos
] )
1523 while( nPos
< nLen
&& sal_Unicode(' ') == rString
[nPos
] )
1528 switch(rString
[nPos
])
1530 case sal_Unicode('%') :
1532 nRetUnit
= MeasureUnit::PERCENT
;
1535 case sal_Unicode('c'):
1536 case sal_Unicode('C'):
1538 if(nPos
+1 < nLen
&& (rString
[nPos
+1] == sal_Unicode('m')
1539 || rString
[nPos
+1] == sal_Unicode('M')))
1540 nRetUnit
= MeasureUnit::CM
;
1543 case sal_Unicode('e'):
1544 case sal_Unicode('E'):
1546 // CSS1_EMS or CSS1_EMX later
1549 case sal_Unicode('i'):
1550 case sal_Unicode('I'):
1552 if(nPos
+1 < nLen
&& (rString
[nPos
+1] == sal_Unicode('n')
1553 || rString
[nPos
+1] == sal_Unicode('n')))
1554 nRetUnit
= MeasureUnit::INCH
;
1557 case sal_Unicode('m'):
1558 case sal_Unicode('M'):
1560 if(nPos
+1 < nLen
&& (rString
[nPos
+1] == sal_Unicode('m')
1561 || rString
[nPos
+1] == sal_Unicode('M')))
1562 nRetUnit
= MeasureUnit::MM
;
1565 case sal_Unicode('p'):
1566 case sal_Unicode('P'):
1568 if(nPos
+1 < nLen
&& (rString
[nPos
+1] == sal_Unicode('t')
1569 || rString
[nPos
+1] == sal_Unicode('T')))
1570 nRetUnit
= MeasureUnit::POINT
;
1571 if(nPos
+1 < nLen
&& (rString
[nPos
+1] == sal_Unicode('c')
1572 || rString
[nPos
+1] == sal_Unicode('C')))
1573 nRetUnit
= MeasureUnit::TWIP
;