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

Generated by: LCOV version 1.10