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

Generated by: LCOV version 1.10