LCOV - code coverage report
Current view: top level - sax/source/tools - converter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1045 1256 83.2 %
Date: 2015-06-13 12:38:46 Functions: 48 51 94.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11