[Libreoffice-commits] .: Branch 'feature/currency-64bit' - 2 commits - basic/source

Noel Power noelp at kemper.freedesktop.org
Tue Dec 14 13:50:33 PST 2010


 basic/source/classes/sbunoobj.cxx |    4 -
 basic/source/sbx/sbxcurr.cxx      |   87 +++++++++++++++++++-------------------
 basic/source/sbx/sbxvalue.cxx     |   38 +++++++---------
 3 files changed, 62 insertions(+), 67 deletions(-)

New commits:
commit 493bea7486f5239b2c35a51369f23f7ef815226d
Author: Noel Power <noel.power at novell.com>
Date:   Tue Dec 14 20:38:17 2010 +0000

    Changes to ImpStringToCurrency
    
    Make ImpStringToCurrency be less of a home grown parser, use existing OUString -> number functionality ( and ws treatment ) Also raise an error now if illegal chars are found in the middle of the string ( including spaces )

diff --git a/basic/source/sbx/sbxcurr.cxx b/basic/source/sbx/sbxcurr.cxx
index 1de0ec4..9278ada 100644
--- a/basic/source/sbx/sbxcurr.cxx
+++ b/basic/source/sbx/sbxcurr.cxx
@@ -118,24 +118,18 @@ static rtl::OUString ImpCurrencyToString( const sal_Int64 &rVal )
 
 static sal_Int64 ImpStringToCurrency( const rtl::OUString &rStr )
 {
-// TODO consider various possible errors: overflow, end-of-string check for leftovers from malformed string
-    sal_Int32   nFractDigit = 4;
-    sal_Int64   nResult = 0;
-    sal_Bool    bNeg = sal_False;
 
-    const sal_Unicode* p = rStr.getStr();
+    sal_Int32   nFractDigit = 4;
 
     SvtSysLocale aSysLocale;
+    sal_Unicode cDeciPnt = sal_Unicode('.');
+    sal_Unicode c1000Sep = sal_Unicode(',');
+
 #if MAYBEFUTURE
     const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
     sal_Unicode cLocaleDeciPnt = rData.getNumDecimalSep().GetBuffer()[0];
     sal_Unicode cLocale1000Sep = rData.getNumThousandSep().GetBuffer()[0];
-#endif
-    sal_Unicode cSpaceSep = sal_Unicode(' ');
-    sal_Unicode cDeciPnt = sal_Unicode('.');
-    sal_Unicode c1000Sep = sal_Unicode(',');
 
-#if MAYBEFUTURE
         // score each set of separators (Locale and Basic) on total number of matches
         // if one set has more matches use that set
         // if tied use the set with the only or rightmost decimal separator match
@@ -171,51 +165,53 @@ static sal_Int64 ImpStringToCurrency( const rtl::OUString &rStr )
     }
 #endif
 
-    //  p == original param value: re-starting at top of string
-    while( *p == cSpaceSep ) p++;                   // skip leading spaces
-    if( *p == sal_Unicode('-') )
-    {
-        p++;
-        bNeg = sal_True;
-    }
-    else if ( *p == sal_Unicode('+') )
-        p++;
+    // lets use the existing string number conversions
+    // there is a performance impact here ( multiple string copies )
+    // but better I think than a home brewed string parser, if we need a parser
+    // we should share some existing ( possibly from calc is there a currency
+    // conversion there ? #TODO check )
+
+    rtl::OUString sTmp( rStr.trim() );
+    const sal_Unicode* p =  sTmp.getStr();
 
-    while( *p == cSpaceSep ) p++;                   // skip space between sign and number
+    // normalise string number by removeing thousands & decimal point seperators
+    rtl::OUStringBuffer sNormalisedNumString( sTmp.getLength() +  nFractDigit );
 
-    // always accept space as thousand separator (is never decimal pt; maybe stray)
-    // exits on non-numeric (incl. null terminator)
-    while( ( *p >= '0' && *p <= '9' ) || *p == c1000Sep || *p == cSpaceSep )
+    if ( *p == '-'  || *p == '+' )
+        sNormalisedNumString.append( *p );
+
+    while ( ( *p >= '0' && *p <= '9' ) )
     {
-        if ( *p >= '0' && *p <= '9' )
-            nResult = 10*nResult + (sal_Int64)*p - (sal_Int64)'0';
-        p++;
-        // could be overflow here ... new result < last result (results always > 0)
+        sNormalisedNumString.append( *p++ );
+        // #TODO in vba mode set runtime error when a space ( or other )
+        // illegal character is found
+        if( *p == c1000Sep )
+            p++;
     }
 
-    if( *p == cDeciPnt ) {
+    if( *p == cDeciPnt )
+    {
         p++;
-        while( (nFractDigit && *p >= '0' && *p <= '9') || *p == cSpaceSep )
+        while( nFractDigit && *p >= '0' && *p <= '9' )
         {
-            nResult = 10*nResult + (sal_Int64)*p - (sal_Int64)'0';
+            sNormalisedNumString.append( *p++ );
             nFractDigit--;
-            p++;
-            // could be overflow here ...
         }
-        while( *p == cSpaceSep ) p++;               // skip mid-number/trailing spaces
-        if( *p >= '5' && *p <= '9' ) nResult ++;    // round 5-9 up = round to nearest
     }
-    while( *p == cSpaceSep ) p++;                   // skip mid-number/trailing spaces
-    // error cases of junky string skip thru to end up here
-    // warning cases of extra num ignored end up here too
+    // can we raise error here ? ( previous behaviour was more forgiving )
+    // so... not sure that could bread existing code, lets see if anyone
+    // complains.
 
-    // make sure all of CURRENCY_FACTOR is applied
-    while( nFractDigit ) {
-        nResult *= 10;
+    if ( p != sTmp.getStr() + sTmp.getLength() )
+        SbxBase::SetError( SbxERR_CONVERSION );
+    while( nFractDigit )
+    {
+        sNormalisedNumString.append( '0' );
         nFractDigit--;
     }
-    if( bNeg )  return -nResult;
-    return nResult;
+
+    sal_Int64 result = sNormalisedNumString.makeStringAndClear().toInt64();
+    return result;
 }
 
 
commit 30c79efc5903edc5bc8994f518c206a608ef3a14
Author: Noel Power <noel.power at novell.com>
Date:   Tue Dec 14 18:23:05 2010 +0000

    redo stream operators & misc changes to prepare to integrate into master

diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx
index bab1cd6..c979455 100644
--- a/basic/source/classes/sbunoobj.cxx
+++ b/basic/source/classes/sbunoobj.cxx
@@ -1149,10 +1149,6 @@ Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType =
                         aType = ::getCppuType( (sal_Int16*)0 );
                     else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
                         aType = ::getCppuType( (sal_Int32*)0 );
-#if MAYBEFUTURE
-                    else
-                        aType = ::getCppuType( (sal_Int64*)0 );
-#endif
                 }
                 break;
             }
diff --git a/basic/source/sbx/sbxcurr.cxx b/basic/source/sbx/sbxcurr.cxx
index f40e0b0..1de0ec4 100644
--- a/basic/source/sbx/sbxcurr.cxx
+++ b/basic/source/sbx/sbxcurr.cxx
@@ -43,8 +43,9 @@ static rtl::OUString ImpCurrencyToString( const sal_Int64 &rVal )
     sal_Int64 absVal = isNeg ? -rVal : rVal;
 
     SvtSysLocale aSysLocale;
-    sal_Unicode cDecimalSep = '.', cThousandSep = ',';
+    sal_Unicode cDecimalSep = '.';
 #if MAYBEFUTURE
+    sal_Unicode cThousandSep = ',';
     const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
     cDecimalSep = rData.getNumDecimalSep().GetBuffer()[0];
     cThousandSep = rData.getNumThousandSep().GetBuffer()[0];
@@ -64,11 +65,13 @@ static rtl::OUString ImpCurrencyToString( const sal_Int64 &rVal )
     if ( !bLessThanOne )
     {
         nCapacity = initialLen + 1;
+#if MAYBEFUTURE
         if ( initialLen > 5 )
         {
             sal_Int32 nThouSeperators = ( initialLen - 5 ) / 3;
             nCapacity += nThouSeperators;
         }
+#endif
     }
 
     if ( isNeg )
@@ -85,8 +88,10 @@ static rtl::OUString ImpCurrencyToString( const sal_Int64 &rVal )
     {
         if ( nDigitCount == 4 )
             aBuf.setCharAt( nInsertIndex--, cDecimalSep );
+#if MAYBEFUTURE
         if ( nDigitCount > 4 && ! ( ( nDigitCount - 4  ) % 3) )
             aBuf.setCharAt( nInsertIndex--, cThousandSep );
+#endif
         if ( nDigitCount < initialLen )
             aBuf.setCharAt( nInsertIndex--, aAbsStr[ charCpyIndex-- ] );
         else
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
index ff30acd..690df56 100644
--- a/basic/source/sbx/sbxvalue.cxx
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -1502,6 +1502,8 @@ BOOL SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
 
 BOOL SbxValue::LoadData( SvStream& r, USHORT )
 {
+    // #TODO see if these types are really dumped to any stream
+    // more than likely this is functionality used in the binfilter alone
     SbxValue::Clear();
     UINT16 nType;
     r >> nType;
@@ -1543,21 +1545,20 @@ BOOL SbxValue::LoadData( SvStream& r, USHORT )
             break;
         }
         case SbxSALUINT64:
-        {
-// TODO fix write for whole 64 bits was Hi then Lo
-            sal_uInt32 tmpHi, tmpLo;
-            r >> tmpHi >> tmpLo;
-            aData.uInt64 = ((sal_Int64)tmpHi << 32) || (sal_Int64)tmpLo;
-            break;
-        }
         case SbxSALINT64:
+            // Rather ugly use of the union here because we only
+            // have a SvStream& SvStream::operator>>(sal_uInt64&) available to us
+            // There is no SvStream::operator>>(sal_Int64&) due to conflict with
+            // SvStream::operator>>(long&) ( at least on 64 bit linux )
+            r >> aData.uInt64;
+            break;
         case SbxCURRENCY:
         {
-// TODO fix write for whole 64 bits was Hi then Lo
-            sal_Int32 tmpHi;
-            sal_uInt32 tmpLo;
+            sal_uInt32 tmpHi = 0;
+            sal_uInt32 tmpLo = 0;
             r >> tmpHi >> tmpLo;
-            aData.nInt64 = ((sal_Int64)tmpHi << 32) || (sal_Int64)tmpLo;
+            aData.nInt64 = ((sal_Int64)tmpHi << 32);
+            aData.nInt64 |= (sal_Int64)tmpLo;
             break;
         }
         case SbxSTRING:
@@ -1667,18 +1668,15 @@ BOOL SbxValue::StoreData( SvStream& r ) const
             r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
             break;
         case SbxSALUINT64:
-        {
-// TODO check output from this
-            sal_uInt32 tmpHi = (aData.uInt64 >> 32);
-            r << tmpHi << (sal_uInt32)(aData.uInt64);
-            break;
-        }
         case SbxSALINT64:
+            // see comment in SbxValue::StoreData
+            r << aData.uInt64;
+            break;
         case SbxCURRENCY:
         {
-// TODO check output from this
-            sal_Int32 tmpHi = (aData.nInt64 >> 32);
-            r << tmpHi << (sal_Int32)(aData.nInt64);
+            sal_Int32 tmpHi = ( (aData.nInt64 >> 32) &  0xFFFFFFFF );
+            sal_Int32 tmpLo = ( sal_Int32 )aData.nInt64;
+            r << tmpHi << tmpLo;
             break;
         }
         case SbxSTRING:


More information about the Libreoffice-commits mailing list