diff options
author | Joachim Lingner <jl@openoffice.org> | 2000-11-21 14:30:56 +0000 |
---|---|---|
committer | Joachim Lingner <jl@openoffice.org> | 2000-11-21 14:30:56 +0000 |
commit | c0b7ad01d1331c131784d01f677da8065b1704ae (patch) | |
tree | 06e28445b33d041a6db48741eebf55b4b4d650e8 /sal/rtl/source/string.c | |
parent | b3f5459f035143a864ccce4d391040a9abbc0d60 (diff) |
rtl_str_valueOfFloat and rtl_str_valueOfDouble implemented
Diffstat (limited to 'sal/rtl/source/string.c')
-rw-r--r-- | sal/rtl/source/string.c | 190 |
1 files changed, 186 insertions, 4 deletions
diff --git a/sal/rtl/source/string.c b/sal/rtl/source/string.c index a81ea1c69dd1..fcbb5d640ca8 100644 --- a/sal/rtl/source/string.c +++ b/sal/rtl/source/string.c @@ -2,9 +2,9 @@ * * $RCSfile: string.c,v $ * - * $Revision: 1.1.1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: hr $ $Date: 2000-09-18 15:17:24 $ + * last change: $Author: jl $ $Date: 2000-11-21 15:30:56 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -83,6 +83,12 @@ #include <rtl/alloc.h> #endif +#include <math.h> + +sal_Int32 SAL_CALL numberToStringImplA(sal_Char * str, double d, sal_Int16 significantDigits ); +sal_Int32 SAL_CALL getInfinityStrA(sal_Char * This, sal_Bool bNeg); +sal_Int32 SAL_CALL getNaNStrA(sal_Char * This); + static sal_Char RTL_STR_DIGITS[] = { '0' , '1' , '2' , '3' , '4' , '5' , @@ -636,17 +642,59 @@ sal_Int32 SAL_CALL rtl_str_valueOfInt64(sal_Char * str, sal_Int64 l, sal_Int16 r /************************************************************************* * rtl_str_valueOfFloat */ +#define singleSignMask ((sal_uInt32)0x80000000) +#define singleExpMask ((sal_uInt32)0x7f800000) +#define singleFractMask (~(singleSignMask|singleExpMask)) +#define singleExpShift ((sal_uInt32)23) + sal_Int32 SAL_CALL rtl_str_valueOfFloat( sal_Char * This, float f) { - return 0; + /* Discover obvious special cases of NaN and Infinity + * (like in Java Ctor FloatingDecimal( float f ) ) */ + sal_uInt32 fBits = *(sal_uInt32*)(&f); + sal_uInt32 binExp = (sal_uInt32)( (fBits & singleExpMask) >> singleExpShift ); + sal_uInt32 fractBits = fBits & singleFractMask; + if ( binExp == (sal_uInt32)(singleExpMask>>singleExpShift) ) + { + if ( fractBits == 0L ) + return getInfinityStrA(This, (sal_Bool)(f < 0.0)); + else + return getNaNStrA(This); + } + return numberToStringImplA( This, (double)f, 8 ); } /************************************************************************* * rtl_str_valueOfDouble */ +#ifndef WNT +#define signMask ((sal_uInt64)0x8000000000000000LL) +#define expMask ((sal_uInt64)0x7ff0000000000000LL) +#else +#define signMask ((sal_uInt64)0x8000000000000000L) +#define expMask ((sal_uInt64)0x7ff0000000000000L) +#endif + +#define fractMask (~(signMask|expMask)) +#define expShift ((sal_uInt32)52) + sal_Int32 SAL_CALL rtl_str_valueOfDouble( sal_Char * This, double d) { - return 0; +#ifndef SAL_INT64_IS_STRUCT + /* Discover obvious special cases of NaN and Infinity. + * (like in Java Ctor FloatingDecimal( double d ) ) */ + sal_uInt64 dBits = *(sal_uInt64*)(&d); + sal_uInt32 binExp = (sal_uInt32)( (dBits & expMask) >> expShift ); + sal_uInt64 fractBits = dBits & fractMask; + if ( binExp == (int)(expMask >> expShift) ) + { + if ( fractBits == 0L ) + return getInfinityStrA(This, (sal_Bool)(d < 0.0)); + else + return getNaNStrA(This); + } +#endif + return numberToStringImplA( This, d, 17 ); } /************************************************************************* @@ -1013,3 +1061,137 @@ void SAL_CALL rtl_string_getToken( rtl_String ** newStr , rtl_String * str, sal_ return; } +/**************************************************************************** +* Internally used functions +*/ +sal_Int32 SAL_CALL numberToStringImplA(sal_Char * str, double d, sal_Int16 significantDigits ) +{ + /* Make it very simple without any formatting, + * (similar to Double.toString() in Java) */ + sal_Char buf[ RTL_STR_MAX_VALUEOFDOUBLE ]; + sal_Char* charPos = buf; + sal_Int16 i, len, dig, dotPos, tmpDot; + sal_Int16 lastNonZeroPos; + sal_Int16 nExpDigits; + sal_Bool bExp, bDotSet; + double dExp, rem; + + if( d == 0 ) + { + *(charPos++) = '0'; + *(charPos++) = '.'; + *(charPos++) = '0'; + } + else + { + if( d < 0 ) + { + *(charPos++) = '-'; + d = -d; + } + + dExp = log10( d ); + bExp = sal_False; + if( dExp > 7 || dExp <= -7 ) + bExp = sal_True; + + dExp = floor( dExp ); + d /= pow( 10, dExp ); + while( d > 10 ) + { + d /= 10.0; + dExp += 1.0; + } + + if( d < 1.0 ) + significantDigits++; + + dotPos = bExp ? 0 : (sal_Int16)dExp; + lastNonZeroPos = 0; + + bDotSet= sal_False; + for( i = 0 ; i < significantDigits ; i++ ) + { + // handle leading zeros + if( dotPos < 0) + { + *(charPos++) = '0'; + *(charPos++) = '.'; + while( ++dotPos < 0) + *(charPos++) = '0'; + bDotSet= sal_True; + } + dig = (sal_Int16)d; + if( dig ) + lastNonZeroPos = i; +// *(charPos++) = L'0' + dig; + *(charPos++) = dig + 0x30; + if( i == dotPos && ! bDotSet) + *(charPos++) = '.'; + d -= (double)dig; + d *= 10.0; + } + + /* Kill trailing zeros */ + if( lastNonZeroPos > dotPos + 1 ) + charPos -= (significantDigits - 1 - lastNonZeroPos); + + /* exponent */ + if( bExp ) + { + *(charPos++) = 'E'; + if( dExp < 0.0 ) + { + dExp = -dExp; + *(charPos++) = '-'; + } + + nExpDigits = 1; + while( dExp >= 10.0 ) + { + nExpDigits++; + dExp /= 10; + } + for( i = 0 ; i < nExpDigits ; i++ ) + { + dig = (sal_Int16)dExp; // sometimes if the debugger shows dExp= 2, the cast produces 1 + rem= fmod( dExp, 1); + if( rem >0.999) // max exponent is about 357 + dig++; + + *(charPos++) = '0' + dig; + dExp -= (double)dig; + dExp *= 10.0; + } + } + } + + *(charPos++) = 0; + len = charPos - buf; + rtl_copyMemory( str, buf, len * sizeof(sal_Char) ); + return len - 1; +} + +/*************************************************************************/ + +sal_Int32 SAL_CALL getInfinityStrA(sal_Char * This, sal_Bool bNeg) +{ + sal_Char InfinityStr[] = "-Infinity"; + sal_Char* pStr = bNeg ? InfinityStr : InfinityStr + 1; + sal_Int32 len = bNeg ? 9 : 8; + sal_Int32 i; + for ( i = 0; i < len+1; i++ ) + *(This+i) = *(pStr+i); + return len; +} + +sal_Int32 SAL_CALL getNaNStrA(sal_Char * This) +{ + sal_Char NaNStr[] = "NaN"; + sal_Int32 len = 3; + sal_Int32 i; + for ( i = 0; i < len+1; i++ ) + *(This+i) = NaNStr[i]; + return len; +} + |