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