/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: converter.cxx,v $ * $Revision: 1.4 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include #include #include #include #include #include "sax/tools/converter.hxx" using namespace rtl; using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::util; //using namespace com::sun::star::text; //using namespace com::sun::star::style; using namespace ::com::sun::star::i18n; namespace sax { static const sal_Char* gpsMM = "mm"; static const sal_Char* gpsCM = "cm"; static const sal_Char* gpsPT = "pt"; static const sal_Char* gpsINCH = "in"; static const sal_Char* gpsPC = "pc"; const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11; const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6; #define XML_NULLDATE "NullDate" /** convert string to measure using optional min and max values*/ bool Converter::convertMeasure( sal_Int32& rValue, const OUString& rString, sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */, sal_Int32 nMin /* = SAL_MIN_INT32 */, sal_Int32 nMax /* = SAL_MAX_INT32 */ ) { bool bNeg = false; double nVal = 0; sal_Int32 nPos = 0L; sal_Int32 nLen = rString.getLength(); // skip white space while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) nPos++; if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) { bNeg = true; nPos++; } // get number while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) { // TODO: check overflow! nVal *= 10; nVal += (rString[nPos] - sal_Unicode('0')); nPos++; } double nDiv = 1.; if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) { nPos++; while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) { // TODO: check overflow! nDiv *= 10; nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv ); nPos++; } } // skip white space while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) nPos++; if( nPos < nLen ) { if( MeasureUnit::PERCENT == nTargetUnit ) { if( sal_Unicode('%') != rString[nPos] ) return false; } else if( MeasureUnit::PIXEL == nTargetUnit ) { if( nPos + 1 >= nLen || (sal_Unicode('p') != rString[nPos] && sal_Unicode('P') != rString[nPos])|| (sal_Unicode('x') != rString[nPos+1] && sal_Unicode('X') != rString[nPos+1]) ) return false; } else { OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit || MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported"); const sal_Char *aCmpsL[2] = { 0, 0 }; const sal_Char *aCmpsU[2] = { 0, 0 }; double aScales[2] = { 1., 1. }; if( MeasureUnit::TWIP == nTargetUnit ) { switch( rString[nPos] ) { case sal_Unicode('c'): case sal_Unicode('C'): aCmpsL[0] = "cm"; aCmpsU[0] = "CM"; aScales[0] = (72.*20.)/2.54; // twip break; case sal_Unicode('i'): case sal_Unicode('I'): aCmpsL[0] = "in"; aCmpsU[0] = "IN"; aScales[0] = 72.*20.; // twip break; case sal_Unicode('m'): case sal_Unicode('M'): aCmpsL[0] = "mm"; aCmpsU[0] = "MM"; aScales[0] = (72.*20.)/25.4; // twip break; case sal_Unicode('p'): case sal_Unicode('P'): aCmpsL[0] = "pt"; aCmpsU[0] = "PT"; aScales[0] = 20.; // twip aCmpsL[1] = "pc"; aCmpsU[1] = "PC"; aScales[1] = 12.*20.; // twip break; } } else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ) { double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0; switch( rString[nPos] ) { case sal_Unicode('c'): case sal_Unicode('C'): aCmpsL[0] = "cm"; aCmpsU[0] = "CM"; aScales[0] = 10.0 * nScaleFactor; // mm/100 break; case sal_Unicode('i'): case sal_Unicode('I'): aCmpsL[0] = "in"; aCmpsU[0] = "IN"; aScales[0] = 1000.*2.54; // mm/100 break; case sal_Unicode('m'): case sal_Unicode('M'): aCmpsL[0] = "mm"; aCmpsU[0] = "MM"; aScales[0] = 1.0 * nScaleFactor; // mm/100 break; case sal_Unicode('p'): case sal_Unicode('P'): aCmpsL[0] = "pt"; aCmpsU[0] = "PT"; aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100 aCmpsL[1] = "pc"; aCmpsU[1] = "PC"; aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100 break; } } else if( MeasureUnit::POINT == nTargetUnit ) { if( rString[nPos] == 'p' || rString[nPos] == 'P' ) { aCmpsL[0] = "pt"; aCmpsU[0] = "PT"; aScales[0] = 1; } } if( aCmpsL[0] == NULL ) return false; double nScale = 0.; for( sal_uInt16 i= 0; i < 2; i++ ) { const sal_Char *pL = aCmpsL[i]; if( pL ) { const sal_Char *pU = aCmpsU[i]; while( nPos < nLen && *pL ) { sal_Unicode c = rString[nPos]; if( c != *pL && c != *pU ) break; pL++; pU++; nPos++; } if( !*pL && (nPos == nLen || ' ' == rString[nPos]) ) { nScale = aScales[i]; break; } } } if( 0. == nScale ) return false; // TODO: check overflow if( nScale != 1. ) nVal *= nScale; } } nVal += .5; if( bNeg ) nVal = -nVal; if( nVal <= (double)nMin ) rValue = nMin; else if( nVal >= (double)nMax ) rValue = nMax; else rValue = (sal_Int32)nVal; return true; } /** convert measure in given unit to string with given unit */ void Converter::convertMeasure( OUStringBuffer& rBuffer, sal_Int32 nMeasure, sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */, sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ ) { OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" ); (void)rBuffer; (void)nMeasure; (void)nSourceUnit; (void)nTargetUnit; #if 0 if( nSourceUnit == MeasureUnit::PERCENT ) { OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" ); rBuffer.append( nMeasure ); rBuffer.append( sal_Unicode('%' ) ); } else { // the sign is processed seperatly if( nMeasure < 0 ) { nMeasure = -nMeasure; rBuffer.append( sal_Unicode('-') ); } // The new length is (nVal * nMul)/(nDiv*nFac*10) long nMul = 1000; long nDiv = 1; long nFac = 100; const sal_Char* psUnit = 0; switch( nSourceUnit ) { case MeasureUnit::TWIP: switch( nTargetUnit ) { case MeasureUnit::MM_100TH: case MeasureUnit::MM_10TH: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" ); case MeasureUnit::MM: // 0.01mm = 0.57twip (exactly) nMul = 25400; // 25.4 * 1000 nDiv = 1440; // 72 * 20; nFac = 100; psUnit = gpsMM; break; case MeasureUnit::CM: // 0.001cm = 0.57twip (exactly) nMul = 25400; // 2.54 * 10000 nDiv = 1440; // 72 * 20; nFac = 1000; psUnit = gpsCM; break; case MeasureUnit::POINT: // 0.01pt = 0.2twip (exactly) nMul = 1000; nDiv = 20; nFac = 100; psUnit = gpsPT; break; case MeasureUnit::INCH: default: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values" ); // 0.0001in = 0.144twip (exactly) nMul = 100000; nDiv = 1440; // 72 * 20; nFac = 10000; psUnit = gpsINCH; break; } break; case MeasureUnit::POINT: // 1pt = 1pt (exactly) OSL_ENSURE( MeasureUnit::POINT == nTargetUnit, "output unit not supported for pt values" ); nMul = 10; nDiv = 1; nFac = 1; psUnit = gpsPT; break; case MeasureUnit::MM_10TH: case MeasureUnit::MM_100TH: { long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10; switch( nTargetUnit ) { case MeasureUnit::MM_100TH: case MeasureUnit::MM_10TH: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values" ); case MeasureUnit::MM: // 0.01mm = 1 mm/100 (exactly) nMul = 10; nDiv = 1; nFac = nFac2; psUnit = gpsMM; break; case MeasureUnit::CM: // 0.001mm = 1 mm/100 (exactly) nMul = 10; nDiv = 1; // 72 * 20; nFac = 10*nFac2; psUnit = gpsCM; break; case MeasureUnit::POINT: // 0.01pt = 0.35 mm/100 (exactly) nMul = 72000; nDiv = 2540; nFac = nFac2; psUnit = gpsPT; break; case MeasureUnit::INCH: default: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values" ); // 0.0001in = 0.254 mm/100 (exactly) nMul = 100000; nDiv = 2540; nFac = 100*nFac2; psUnit = gpsINCH; break; } break; } } long nLongVal = 0; bool bOutLongVal = true; if( nMeasure > SAL_INT32_MAX / nMul ) { // A big int is required for calculation BigInt nBigVal( nMeasure ); BigInt nBigFac( nFac ); nBigVal *= nMul; nBigVal /= nDiv; nBigVal += 5; nBigVal /= 10; if( nBigVal.IsLong() ) { // To convert the value into a string a long is sufficient nLongVal = (long)nBigVal; } else { BigInt nBigFac2( nFac ); BigInt nBig10( 10 ); rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) ); if( !(nBigVal % nBigFac2).IsZero() ) { rBuffer.append( sal_Unicode('.') ); while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() ) { nFac /= 10; nBigFac2 = nFac; rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) ); } } bOutLongVal = false; } } else { nLongVal = nMeasure * nMul; nLongVal /= nDiv; nLongVal += 5; nLongVal /= 10; } if( bOutLongVal ) { rBuffer.append( (sal_Int32)(nLongVal / nFac) ); if( nFac > 1 && (nLongVal % nFac) != 0 ) { rBuffer.append( sal_Unicode('.') ); while( nFac > 1 && (nLongVal % nFac) != 0 ) { nFac /= 10; rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) ); } } } if( psUnit ) rBuffer.appendAscii( psUnit ); } #endif } static const OUString& getTrueString() { static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) ); return sTrue; } static const OUString& getFalseString() { static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) ); return sFalse; } /** convert string to boolean */ bool Converter::convertBool( bool& rBool, const OUString& rString ) { rBool = rString == getTrueString(); return rBool || (rString == getFalseString()); } /** convert boolean to string */ void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue ) { rBuffer.append( bValue ? getTrueString() : getFalseString() ); } /** convert string to percent */ bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString ) { return convertMeasure( rPercent, rString, MeasureUnit::PERCENT ); } /** convert percent to string */ void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue ) { rBuffer.append( nValue ); rBuffer.append( sal_Unicode('%' ) ); } /** convert string to pixel measure */ bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString ) { return convertMeasure( rPixel, rString, MeasureUnit::PIXEL ); } /** convert pixel measure to string */ void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue ) { rBuffer.append( nValue ); rBuffer.append( sal_Unicode('p' ) ); rBuffer.append( sal_Unicode('x' ) ); } int lcl_gethex( int nChar ) { if( nChar >= '0' && nChar <= '9' ) return nChar - '0'; else if( nChar >= 'a' && nChar <= 'f' ) return nChar - 'a' + 10; else if( nChar >= 'A' && nChar <= 'F' ) return nChar - 'A' + 10; else return 0; } /** convert string to color */ bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue ) { if( rValue.getLength() != 7 || rValue[0] != '#' ) return false; rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] ); rColor <<= 8; rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) ); rColor <<= 8; rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) ); return true; } static sal_Char aHexTab[] = "0123456789abcdef"; /** convert color to string */ void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor ) { rBuffer.append( sal_Unicode( '#' ) ); sal_uInt8 nCol = (sal_uInt8)(nColor >> 16); rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); nCol = (sal_uInt8)(nColor >> 8); rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); nCol = (sal_uInt8)nColor; rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); } /** convert number to string */ void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber ) { rBuffer.append( nNumber ); } /** convert string to number with optional min and max values */ bool Converter::convertNumber( sal_Int32& rValue, const OUString& rString, sal_Int32 nMin, sal_Int32 nMax ) { bool bNeg = false; rValue = 0; sal_Int32 nPos = 0L; sal_Int32 nLen = rString.getLength(); // skip white space while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) nPos++; if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) { bNeg = true; nPos++; } // get number while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) { // TODO: check overflow! rValue *= 10; rValue += (rString[nPos] - sal_Unicode('0')); nPos++; } if( bNeg ) rValue *= -1; if( rValue < nMin ) rValue = nMin; else if( rValue > nMax ) rValue = nMax; return nPos == nLen; } /** convert double number to string (using ::rtl::math) */ void Converter::convertDouble( OUStringBuffer& rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit) { if(MeasureUnit::PERCENT == nSourceUnit) { OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" ); ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); if(bWriteUnits) rBuffer.append(sal_Unicode('%')); } else { OUStringBuffer sUnit; double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit); if(fFactor != 1.0) fNumber *= fFactor; ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); if(bWriteUnits) rBuffer.append(sUnit); } } /** convert double number to string (using ::rtl::math) */ void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber) { ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); } /** convert string to double number (using ::rtl::math) */ bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString, sal_Int16 nTargetUnit) { sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit); return convertDouble(rValue, rString, nSourceUnit, nTargetUnit ); } /** convert string to double number (using ::rtl::math) */ bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit) { rtl_math_ConversionStatus eStatus; rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); if(eStatus == rtl_math_ConversionStatus_Ok) { OUStringBuffer sUnit; double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit); if(fFactor != 1.0 && fFactor != 0.0) rValue /= fFactor; } return ( eStatus == rtl_math_ConversionStatus_Ok ); } /** convert string to double number (using ::rtl::math) */ bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString) { rtl_math_ConversionStatus eStatus; rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); return ( eStatus == rtl_math_ConversionStatus_Ok ); } /** convert double to ISO "duration" string; negative durations allowed */ void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer, const double fTime) { double fValue = fTime; // take care of negative durations as specified in: // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1 if (fValue < 0.0) { rBuffer.append(sal_Unicode('-')); fValue = - fValue; } rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" )); fValue *= 24; double fHoursValue = ::rtl::math::approxFloor (fValue); fValue -= fHoursValue; fValue *= 60; double fMinsValue = ::rtl::math::approxFloor (fValue); fValue -= fMinsValue; fValue *= 60; double fSecsValue = ::rtl::math::approxFloor (fValue); fValue -= fSecsValue; double f100SecsValue; if (fValue > 0.00001) f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5); else f100SecsValue = 0.0; if (f100SecsValue == 1.0) { f100SecsValue = 0.0; fSecsValue += 1.0; } if (fSecsValue >= 60.0) { fSecsValue -= 60.0; fMinsValue += 1.0; } if (fMinsValue >= 60.0) { fMinsValue -= 60.0; fHoursValue += 1.0; } if (fHoursValue < 10) rBuffer.append( sal_Unicode('0')); rBuffer.append( sal_Int32( fHoursValue)); rBuffer.append( sal_Unicode('H')); if (fMinsValue < 10) rBuffer.append( sal_Unicode('0')); rBuffer.append( sal_Int32( fMinsValue)); rBuffer.append( sal_Unicode('M')); if (fSecsValue < 10) rBuffer.append( sal_Unicode('0')); rBuffer.append( sal_Int32( fSecsValue)); if (f100SecsValue > 0.0) { ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue, rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.', true)); if ( a100th.getLength() > 2 ) { rBuffer.append( sal_Unicode('.')); rBuffer.append( a100th.copy( 2 ) ); // strip 0. } } rBuffer.append( sal_Unicode('S')); } /** convert ISO "duration" string to double; negative durations allowed */ bool Converter::convertDuration(double& rfTime, const ::rtl::OUString& rString) { rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); const sal_Unicode* pStr = aTrimmed.getStr(); // negative time duration? bool bIsNegativeDuration = false; if ( sal_Unicode('-') == (*pStr) ) { bIsNegativeDuration = true; pStr++; } if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" return false; rtl::OUString sDoubleStr; bool bSuccess = true; bool bDone = false; bool bTimePart = false; bool bIsFraction = false; sal_Int32 nDays = 0; sal_Int32 nHours = 0; sal_Int32 nMins = 0; sal_Int32 nSecs = 0; sal_Int32 nTemp = 0; while ( bSuccess && !bDone ) { sal_Unicode c = *(pStr++); if ( !c ) // end bDone = true; else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c ) { if ( nTemp >= SAL_MAX_INT32 / 10 ) bSuccess = false; else { if ( !bIsFraction ) { nTemp *= 10; nTemp += (c - sal_Unicode('0')); } else { sDoubleStr += OUString::valueOf(c); } } } else if ( bTimePart ) { if ( c == sal_Unicode('H') ) { nHours = nTemp; nTemp = 0; } else if ( c == sal_Unicode('M') ) { nMins = nTemp; nTemp = 0; } else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) ) { nSecs = nTemp; nTemp = 0; bIsFraction = true; sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); } else if ( c == sal_Unicode('S') ) { if ( !bIsFraction ) { nSecs = nTemp; nTemp = 0; sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); } } else bSuccess = false; // invalid character } else { if ( c == sal_Unicode('T') ) // "T" starts time part bTimePart = true; else if ( c == sal_Unicode('D') ) { nDays = nTemp; nTemp = 0; } else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') ) { //! how many days is a year or month? OSL_ENSURE( false, "years or months in duration: not implemented"); bSuccess = false; } else bSuccess = false; // invalid character } } if ( bSuccess ) { if ( nDays ) nHours += nDays * 24; // add the days to the hours part double fTempTime = 0.0; double fHour = nHours; double fMin = nMins; double fSec = nSecs; double fSec100 = 0.0; double fFraction = sDoubleStr.toDouble(); fTempTime = fHour / 24; fTempTime += fMin / (24 * 60); fTempTime += fSec / (24 * 60 * 60); fTempTime += fSec100 / (24 * 60 * 60 * 60); fTempTime += fFraction / (24 * 60 * 60); // negative duration? if ( bIsNegativeDuration ) { fTempTime = -fTempTime; } rfTime = fTempTime; } return bSuccess; } /** convert util::Duration to ISO "duration" string */ void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer, const ::util::Duration& rDuration) { if (rDuration.Negative) { rBuffer.append(sal_Unicode('-')); } rBuffer.append(sal_Unicode('P')); const bool bHaveDate(static_cast(rDuration.Years) +static_cast(rDuration.Months) +static_cast(rDuration.Days)); if (rDuration.Years) { rBuffer.append(static_cast(rDuration.Years)); rBuffer.append(sal_Unicode('Y')); } if (rDuration.Months) { rBuffer.append(static_cast(rDuration.Months)); rBuffer.append(sal_Unicode('M')); } if (rDuration.Days) { rBuffer.append(static_cast(rDuration.Days)); rBuffer.append(sal_Unicode('D')); } const sal_Int32 nHSecs(static_cast(rDuration.Seconds) + static_cast(rDuration.HundredthSeconds)); if (static_cast(rDuration.Hours) + static_cast(rDuration.Minutes) + nHSecs) { rBuffer.append(sal_Unicode('T')); // time separator if (rDuration.Hours) { rBuffer.append(static_cast(rDuration.Hours)); rBuffer.append(sal_Unicode('H')); } if (rDuration.Minutes) { rBuffer.append(static_cast(rDuration.Minutes)); rBuffer.append(sal_Unicode('M')); } if (nHSecs) { // seconds must not be omitted (i.e. ".42S" is not valid) rBuffer.append(static_cast(rDuration.Seconds)); if (rDuration.HundredthSeconds) { rBuffer.append(sal_Unicode('.')); const sal_Int32 nHundredthSeconds( rDuration.HundredthSeconds % 100); if (nHundredthSeconds < 10) { rBuffer.append(sal_Unicode('0')); } rBuffer.append(nHundredthSeconds); } rBuffer.append(sal_Unicode('S')); } } else if (!bHaveDate) { // zero duration: XMLSchema-2 says there must be at least one component rBuffer.append(sal_Unicode('0')); rBuffer.append(sal_Unicode('D')); } } enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS }; static Result readUnsignedNumber(const ::rtl::OUString & rString, sal_Int32 & io_rnPos, sal_Int32 & o_rNumber) { bool bOverflow(false); sal_Int32 nTemp(0); for (sal_Int32 nPos = io_rnPos; (nPos < rString.getLength()); ++nPos) { const sal_Unicode c = rString[nPos]; if ((sal_Unicode('0') <= c) && (c <= sal_Unicode('9'))) { nTemp *= 10; nTemp += (c - sal_Unicode('0')); if (nTemp >= SAL_MAX_INT16) { bOverflow = true; } } else { if (io_rnPos != nPos) // read something? { io_rnPos = nPos; if (bOverflow) { return R_OVERFLOW; } else { o_rNumber = nTemp; return R_SUCCESS; } } else break; } } o_rNumber = -1; return R_NOTHING; } static bool readDurationT(const ::rtl::OUString & rString, sal_Int32 & io_rnPos) { if ((io_rnPos < rString.getLength()) && (rString[io_rnPos] == sal_Unicode('T'))) { ++io_rnPos; return true; } return false; } static bool readDurationComponent(const ::rtl::OUString & rString, sal_Int32 & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart, sal_Int32 & o_rnTarget, const sal_Unicode c) { if ((io_rnPos < rString.getLength())) { if (c == rString[io_rnPos]) { ++io_rnPos; if (-1 != io_rnTemp) { o_rnTarget = io_rnTemp; io_rnTemp = -1; if (!io_rbTimePart) { io_rbTimePart = readDurationT(rString, io_rnPos); } return (R_OVERFLOW != readUnsignedNumber(rString, io_rnPos, io_rnTemp)); } else { return false; } } } return true; } /** convert ISO "duration" string to util::Duration */ bool Converter::convertDuration(util::Duration& rDuration, const ::rtl::OUString& rString) { const ::rtl::OUString string = rString.trim().toAsciiUpperCase(); sal_Int32 nPos(0); bool bIsNegativeDuration(false); if (string.getLength() && (sal_Unicode('-') == string[0])) { bIsNegativeDuration = true; ++nPos; } if ((nPos < string.getLength()) && (string[nPos] != sal_Unicode('P'))) // duration must start with "P" { return false; } ++nPos; /// last read number; -1 == no valid number! always reset after using! sal_Int32 nTemp(-1); bool bTimePart(false); // have we read 'T'? bool bSuccess(false); sal_Int32 nYears(0); sal_Int32 nMonths(0); sal_Int32 nDays(0); sal_Int32 nHours(0); sal_Int32 nMinutes(0); sal_Int32 nSeconds(0); sal_Int32 nHundredthSeconds(0); bTimePart = readDurationT(string, nPos); bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp)); if (!bTimePart && bSuccess) { bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart, nYears, sal_Unicode('Y')); } if (!bTimePart && bSuccess) { bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart, nMonths, sal_Unicode('M')); } if (!bTimePart && bSuccess) { bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart, nDays, sal_Unicode('D')); } if (bTimePart) { if (-1 == nTemp) // a 'T' must be followed by a component { bSuccess = false; } if (bSuccess) { bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart, nHours, sal_Unicode('H')); } if (bSuccess) { bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart, nMinutes, sal_Unicode('M')); } // eeek! seconds are icky. if ((nPos < string.getLength()) && bSuccess) { if (sal_Unicode('.') == string[nPos]) { ++nPos; if (-1 != nTemp) { nSeconds = nTemp; nTemp = -1; const sal_Int32 nStart(nPos); bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp)); if ((nPos < string.getLength()) && bSuccess) { if (sal_Unicode('S') == string[nPos]) { ++nPos; if (-1 != nTemp) { nTemp = -1; const sal_Int32 nDigits = nPos - nStart; OSL_ENSURE(nDigits > 0, "bad code monkey"); nHundredthSeconds = 10 * (string[nStart] - sal_Unicode('0')); if (nDigits >= 2) { nHundredthSeconds += (string[nStart+1] - sal_Unicode('0')); } } else { bSuccess = false; } } } } else { bSuccess = false; } } else if (sal_Unicode('S') == string[nPos]) { ++nPos; if (-1 != nTemp) { nSeconds = nTemp; nTemp = -1; } else { bSuccess = false; } } } } if (nPos != string.getLength()) // string not processed completely? { bSuccess = false; } if (nTemp != -1) // unprocessed number? { bSuccess = false; } if (bSuccess) { rDuration.Negative = bIsNegativeDuration; rDuration.Years = static_cast(nYears); rDuration.Months = static_cast(nMonths); rDuration.Days = static_cast(nDays); rDuration.Hours = static_cast(nHours); rDuration.Minutes = static_cast(nMinutes); rDuration.Seconds = static_cast(nSeconds); rDuration.HundredthSeconds = static_cast(nHundredthSeconds); } return bSuccess; } #if 0 //FIXME struct Test { static bool eqDuration(util::Duration a, util::Duration b) { return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days && a.Hours == b.Hours && a.Minutes == b.Minutes && a.Seconds == b.Seconds && a.HundredthSeconds == b.HundredthSeconds && a.Negative == b.Negative; } static void doTest(util::Duration const & rid, const char * pis) { bool bSuccess(false); ::rtl::OUStringBuffer buf; Converter::convertDuration(buf, rid); ::rtl::OUString os(buf.makeStringAndClear()); OSL_TRACE(::rtl::OUStringToOString(os.getStr(), RTL_TEXTENCODING_UTF8)); OSL_ASSERT(os.equalsAscii(pis)); util::Duration od; bSuccess = Converter::convertDuration(od, os); OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH", od.Negative, od.Years, od.Months, od.Days, od.Hours, od.Minutes, od.Seconds, od.HundredthSeconds); OSL_ASSERT(bSuccess); OSL_ASSERT(eqDuration(rid, od)); } static void doTestF(const char * pis) { util::Duration od; bool bSuccess = Converter::convertDuration(od, ::rtl::OUString::createFromAscii(pis)); OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH", od.Negative, od.Years, od.Months, od.Days, od.Hours, od.Minutes, od.Seconds, od.HundredthSeconds); OSL_ASSERT(!bSuccess); } Test() { OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n"); doTest( util::Duration(false, 1, 0, 0, 0, 0, 0, 0), "P1Y" ); doTest( util::Duration(false, 0, 42, 0, 0, 0, 0, 0), "P42M" ); doTest( util::Duration(false, 0, 0, 111, 0, 0, 0, 0), "P111D" ); doTest( util::Duration(false, 0, 0, 0, 52, 0, 0, 0), "PT52H" ); doTest( util::Duration(false, 0, 0, 0, 0, 717, 0, 0), "PT717M" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 121, 0), "PT121S" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 19), "PT0.19S" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.09S" ); doTest( util::Duration(true , 0, 0, 9999, 0, 0, 0, 0), "-P9999D" ); doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 1), "-P7Y6M5DT4H3M2.01S" ); doTest( util::Duration(false, 0, 6, 0, 0, 3, 0, 0), "P6MT3M" ); doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 0), "P0D" ); doTestF("1Y1M"); doTestF("P-1Y1M"); doTestF("P1M1Y"); doTestF("PT1Y"); doTestF("P1Y1M1M"); doTestF("P1YT1MT1M"); doTestF("P1YT"); doTestF("P99999999999Y"); doTestF("PT.1S"); doTestF("PT5M.134S"); doTestF("PT1.S"); OSL_TRACE("\nSAX CONVERTER TEST END\n"); } }; static Test test; #endif /** convert util::Date to ISO "date" string */ void Converter::convertDate( ::rtl::OUStringBuffer& i_rBuffer, const util::Date& i_rDate) { const util::DateTime dt( 0, 0, 0, 0, i_rDate.Day, i_rDate.Month, i_rDate.Year); convertDateTime(i_rBuffer, dt, false); } /** convert util::DateTime to ISO "date" or "dateTime" string */ void Converter::convertDateTime( ::rtl::OUStringBuffer& i_rBuffer, const com::sun::star::util::DateTime& i_rDateTime, bool i_bAddTimeIf0AM ) { const sal_Unicode dash('-'); const sal_Unicode col (':'); const sal_Unicode dot ('.'); const sal_Unicode zero('0'); const sal_Unicode tee ('T'); i_rBuffer.append( static_cast(i_rDateTime.Year) ).append(dash); if( i_rDateTime.Month < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.Month) ).append(dash); if( i_rDateTime.Day < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.Day) ); if( i_rDateTime.Seconds != 0 || i_rDateTime.Minutes != 0 || i_rDateTime.Hours != 0 || i_bAddTimeIf0AM ) { i_rBuffer.append(tee); if( i_rDateTime.Hours < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.Hours) ) .append(col); if( i_rDateTime.Minutes < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.Minutes) ) .append(col); if( i_rDateTime.Seconds < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.Seconds) ); if( i_rDateTime.HundredthSeconds > 0 ) { i_rBuffer.append(dot); if( i_rDateTime.HundredthSeconds < 10 ) { i_rBuffer.append(zero); } i_rBuffer.append( static_cast(i_rDateTime.HundredthSeconds) ); } } } /** convert ISO "date" or "dateTime" string to util::DateTime */ bool Converter::convertDateTime( util::DateTime& rDateTime, const ::rtl::OUString& rString ) { bool isDateTime; util::Date date; if (convertDateOrDateTime(date, rDateTime, isDateTime, rString)) { if (!isDateTime) { rDateTime.Year = date.Year; rDateTime.Month = date.Month; rDateTime.Day = date.Day; rDateTime.Hours = 0; rDateTime.Minutes = 0; rDateTime.Seconds = 0; rDateTime.HundredthSeconds = 0; } return true; } else { return false; } } /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */ bool Converter::convertDateOrDateTime( util::Date & rDate, util::DateTime & rDateTime, bool & rbDateTime, const ::rtl::OUString & rString ) { bool bSuccess = true; rtl::OUString aDateStr, aTimeStr, sDoubleStr; sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' ); sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' ); if (nPos2 < 0) nPos2 = rString.indexOf( (sal_Unicode) '.' ); if ( nPos >= 0 ) { aDateStr = rString.copy( 0, nPos ); if ( nPos2 >= 0 ) { aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 ); sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); sDoubleStr += rString.copy( nPos2 + 1 ); } else { aTimeStr = rString.copy(nPos + 1); sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); } } else aDateStr = rString; // no separator: only date part sal_Int32 nYear = 1899; sal_Int32 nMonth = 12; sal_Int32 nDay = 30; sal_Int32 nHour = 0; sal_Int32 nMin = 0; sal_Int32 nSec = 0; const sal_Unicode* pStr = aDateStr.getStr(); sal_Int32 nDateTokens = 1; while ( *pStr ) { if ( *pStr == '-' ) nDateTokens++; pStr++; } if ( nDateTokens > 3 || aDateStr.getLength() == 0 ) bSuccess = false; else { sal_Int32 n = 0; if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) bSuccess = false; if ( nDateTokens >= 2 ) if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) bSuccess = false; if ( nDateTokens >= 3 ) if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) bSuccess = false; } if ( aTimeStr.getLength() > 0 ) // time is optional { pStr = aTimeStr.getStr(); sal_Int32 nTimeTokens = 1; while ( *pStr ) { if ( *pStr == ':' ) nTimeTokens++; pStr++; } if ( nTimeTokens > 3 ) bSuccess = false; else { sal_Int32 n = 0; if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) bSuccess = false; if ( nTimeTokens >= 2 ) if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) bSuccess = false; if ( nTimeTokens >= 3 ) if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) bSuccess = false; } } if (bSuccess) { if ( aTimeStr.getLength() > 0 ) // time is optional { rDateTime.Year = static_cast(nYear); rDateTime.Month = static_cast(nMonth); rDateTime.Day = static_cast(nDay); rDateTime.Hours = static_cast(nHour); rDateTime.Minutes = static_cast(nMin); rDateTime.Seconds = static_cast(nSec); rDateTime.HundredthSeconds = static_cast((sDoubleStr).toDouble() * 100); rbDateTime = true; } else { rDate.Year = static_cast(nYear); rDate.Month = static_cast(nMonth); rDate.Day = static_cast(nDay); rbDateTime = false; } } return bSuccess; } /** gets the position of the first comma after npos in the string rStr. Commas inside '"' pairs are not matched */ sal_Int32 Converter::indexOfComma( const OUString& rStr, sal_Int32 nPos ) { sal_Unicode cQuote = 0; sal_Int32 nLen = rStr.getLength(); for( ; nPos < nLen; nPos++ ) { sal_Unicode c = rStr[nPos]; switch( c ) { case sal_Unicode('\''): if( 0 == cQuote ) cQuote = c; else if( '\'' == cQuote ) cQuote = 0; break; case sal_Unicode('"'): if( 0 == cQuote ) cQuote = c; else if( '\"' == cQuote ) cQuote = 0; break; case sal_Unicode(','): if( 0 == cQuote ) return nPos; break; } } return -1; } const sal_Char aBase64EncodeTable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; const sal_uInt8 aBase64DecodeTable[] = { 62,255,255,255, 63, // 43-47 // + / 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63 // 0 1 2 3 4 5 6 7 8 9 = 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 // A B C D E F G H I J K L M N O 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95 // P Q R S T U V W X Y Z 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 // a b c d e f g h i j k l m n o 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123 // p q r s t u v w x y z void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer) { sal_Int32 nLen(nFullLen - nStart); if (nLen > 3) nLen = 3; if (nLen == 0) { sBuffer.setLength(0); return; } sal_Int32 nBinaer; switch (nLen) { case 1: { nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16; } break; case 2: { nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + (((sal_uInt8)pBuffer[nStart + 1]) << 8); } break; default: { nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + (((sal_uInt8)pBuffer[nStart + 1]) << 8) + ((sal_uInt8)pBuffer[nStart + 2]); } break; } sBuffer.appendAscii("===="); sal_uInt8 nIndex (static_cast((nBinaer & 0xFC0000) >> 18)); sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]); nIndex = static_cast((nBinaer & 0x3F000) >> 12); sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]); if (nLen == 1) return; nIndex = static_cast((nBinaer & 0xFC0) >> 6); sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]); if (nLen == 2) return; nIndex = static_cast((nBinaer & 0x3F)); sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]); } void Converter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence& aPass) { sal_Int32 i(0); sal_Int32 nBufferLength(aPass.getLength()); const sal_Int8* pBuffer = aPass.getConstArray(); while (i < nBufferLength) { rtl::OUStringBuffer sBuffer; ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer); aStrBuffer.append(sBuffer); i += 3; } } void Converter::decodeBase64(uno::Sequence& aBuffer, const rtl::OUString& sBuffer) { #if OSL_DEBUG_LEVEL > 0 sal_Int32 nCharsDecoded = #endif decodeBase64SomeChars( aBuffer, sBuffer ); OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" ); } sal_Int32 Converter::decodeBase64SomeChars( uno::Sequence& rOutBuffer, const rtl::OUString& rInBuffer) { sal_Int32 nInBufferLen = rInBuffer.getLength(); sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3; if( rOutBuffer.getLength() < nMinOutBufferLen ) rOutBuffer.realloc( nMinOutBufferLen ); const sal_Unicode *pInBuffer = rInBuffer.getStr(); sal_Int8 *pOutBuffer = rOutBuffer.getArray(); sal_Int8 *pOutBufferStart = pOutBuffer; sal_Int32 nCharsDecoded = 0; sal_uInt8 aDecodeBuffer[4]; sal_Int32 nBytesToDecode = 0; sal_Int32 nBytesGotFromDecoding = 3; sal_Int32 nInBufferPos= 0; while( nInBufferPos < nInBufferLen ) { sal_Unicode cChar = *pInBuffer; if( cChar >= '+' && cChar <= 'z' ) { sal_uInt8 nByte = aBase64DecodeTable[cChar-'+']; if( nByte != 255 ) { // We have found a valid character! aDecodeBuffer[nBytesToDecode++] = nByte; // One '=' character at the end means 2 out bytes // Two '=' characters at the end mean 1 out bytes if( '=' == cChar && nBytesToDecode > 2 ) nBytesGotFromDecoding--; if( 4 == nBytesToDecode ) { // Four characters found, so we may convert now! sal_uInt32 nOut = (aDecodeBuffer[0] << 18) + (aDecodeBuffer[1] << 12) + (aDecodeBuffer[2] << 6) + aDecodeBuffer[3]; *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16); if( nBytesGotFromDecoding > 1 ) *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8); if( nBytesGotFromDecoding > 2 ) *pOutBuffer++ = (sal_Int8)(nOut & 0xff); nCharsDecoded = nInBufferPos + 1; nBytesToDecode = 0; nBytesGotFromDecoding = 3; } } else { nCharsDecoded++; } } else { nCharsDecoded++; } nInBufferPos++; pInBuffer++; } if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() ) rOutBuffer.realloc( pOutBuffer - pOutBufferStart ); return nCharsDecoded; } void Converter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource) { sal_uInt32 nLength(rSource.getLength()); rtl::OUStringBuffer sBuffer(nLength); for (sal_uInt32 i = 0; i < nLength; i++) { sal_Unicode cChar = rSource[i]; if (!(cChar < 0x0020) || (cChar == 0x0009) || // TAB (cChar == 0x000A) || // LF (cChar == 0x000D)) // legal character sBuffer.append(cChar); } rTarget = sBuffer.makeStringAndClear(); } double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit) { double fRetval(1.0); rUnit.setLength(0L); const sal_Char* psUnit = 0; if(nSourceUnit != nTargetUnit) { switch(nSourceUnit) { case MeasureUnit::TWIP: { switch(nTargetUnit) { case MeasureUnit::MM_100TH: case MeasureUnit::MM_10TH: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values"); } case MeasureUnit::MM: { // 0.01mm = 0.57twip (exactly) fRetval = ((25400.0 / 1440.0) / 1000.0); psUnit = gpsMM; break; } case MeasureUnit::CM: { // 0.001cm = 0.57twip (exactly) fRetval = ((25400.0 / 1440.0) / 10000.0); psUnit = gpsCM; break; } case MeasureUnit::POINT: { // 0.01pt = 0.2twip (exactly) fRetval = ((1000.0 / 20.0) / 1000.0); psUnit = gpsPT; break; } case MeasureUnit::INCH: default: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values"); // 0.0001in = 0.144twip (exactly) fRetval = ((100000.0 / 1440.0) / 100000.0); psUnit = gpsINCH; break; } } break; } case MeasureUnit::POINT: { switch(nTargetUnit) { case MeasureUnit::MM: // 1mm = 72 / 25.4 pt (exactly) fRetval = ( 25.4 / 72.0 ); psUnit = gpsMM; break; case MeasureUnit::CM: // 1cm = 72 / 2.54 pt (exactly) fRetval = ( 2.54 / 72.0 ); psUnit = gpsCM; break; case MeasureUnit::TWIP: // 1twip = 72 / 1440 pt (exactly) fRetval = 20.0; // 1440.0 / 72.0 psUnit = gpsPC; break; case MeasureUnit::INCH: default: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values"); // 1in = 72 pt (exactly) fRetval = ( 1.0 / 72.0 ); psUnit = gpsINCH; break; } break; } case MeasureUnit::MM_10TH: { switch(nTargetUnit) { case MeasureUnit::MM_100TH: case MeasureUnit::MM_10TH: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); } case MeasureUnit::MM: { // 0.01mm = 1 mm/100 (exactly) fRetval = ((10.0 / 1.0) / 100.0); psUnit = gpsMM; break; } case MeasureUnit::CM: { // 0.001mm = 1 mm/100 (exactly) fRetval = ((10.0 / 1.0) / 1000.0); psUnit = gpsCM; break; } case MeasureUnit::POINT: { // 0.01pt = 0.35 mm/100 (exactly) fRetval = ((72000.0 / 2540.0) / 100.0); psUnit = gpsPT; break; } case MeasureUnit::INCH: default: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); // 0.0001in = 0.254 mm/100 (exactly) fRetval = ((100000.0 / 2540.0) / 10000.0); psUnit = gpsINCH; break; } } break; } case MeasureUnit::MM_100TH: { switch(nTargetUnit) { case MeasureUnit::MM_100TH: case MeasureUnit::MM_10TH: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); } case MeasureUnit::MM: { // 0.01mm = 1 mm/100 (exactly) fRetval = ((10.0 / 1.0) / 1000.0); psUnit = gpsMM; break; } case MeasureUnit::CM: { // 0.001mm = 1 mm/100 (exactly) fRetval = ((10.0 / 1.0) / 10000.0); psUnit = gpsCM; break; } case MeasureUnit::POINT: { // 0.01pt = 0.35 mm/100 (exactly) fRetval = ((72000.0 / 2540.0) / 1000.0); psUnit = gpsPT; break; } case MeasureUnit::INCH: default: { OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); // 0.0001in = 0.254 mm/100 (exactly) fRetval = ((100000.0 / 2540.0) / 100000.0); psUnit = gpsINCH; break; } } break; } } if( psUnit ) rUnit.appendAscii( psUnit ); } return fRetval; } sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit) { sal_Int32 nPos = 0L; sal_Int32 nLen = rString.getLength(); sal_Int16 nRetUnit = nDefaultUnit; // skip white space while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) nPos++; // skip negative if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) nPos++; // skip number while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) nPos++; if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) { nPos++; while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) nPos++; } // skip white space while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) nPos++; if( nPos < nLen ) { switch(rString[nPos]) { case sal_Unicode('%') : { nRetUnit = MeasureUnit::PERCENT; break; } case sal_Unicode('c'): case sal_Unicode('C'): { if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') || rString[nPos+1] == sal_Unicode('M'))) nRetUnit = MeasureUnit::CM; break; } case sal_Unicode('e'): case sal_Unicode('E'): { // CSS1_EMS or CSS1_EMX later break; } case sal_Unicode('i'): case sal_Unicode('I'): { if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n') || rString[nPos+1] == sal_Unicode('n'))) nRetUnit = MeasureUnit::INCH; break; } case sal_Unicode('m'): case sal_Unicode('M'): { if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') || rString[nPos+1] == sal_Unicode('M'))) nRetUnit = MeasureUnit::MM; break; } case sal_Unicode('p'): case sal_Unicode('P'): { if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t') || rString[nPos+1] == sal_Unicode('T'))) nRetUnit = MeasureUnit::POINT; if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c') || rString[nPos+1] == sal_Unicode('C'))) nRetUnit = MeasureUnit::TWIP; break; } } } return nRetUnit; } }