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

Generated by: LCOV version 1.10