From 94112ff96056178724d7a2743c55db8922a9c3be Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 21 Apr 2010 11:26:22 +0200 Subject: [PATCH] msvcrt: Added _strtod_l implementation. --- dlls/msvcr80/msvcr80.spec | 2 +- dlls/msvcr90/msvcr90.spec | 2 +- dlls/msvcrt/msvcrt.spec | 2 +- dlls/msvcrt/string.c | 62 +++++++++++++++++++++++++++++++++++++- dlls/msvcrt/tests/string.c | 56 ++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 4 deletions(-) diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index 0023a15bc3e..cec87368f1c 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -957,7 +957,7 @@ @ stub _strset_s @ cdecl _strtime(ptr) msvcrt._strtime @ stub _strtime_s -@ stub _strtod_l +@ cdecl _strtod_l(str ptr ptr) msvcrt._strtod_l @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ stub _strtol_l diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index add61f771e1..16ec74b0e0c 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -943,7 +943,7 @@ @ stub _strset_s @ cdecl _strtime(ptr) msvcrt._strtime @ stub _strtime_s -@ stub _strtod_l +@ cdecl _strtod_l(str ptr ptr) msvcrt._strtod_l @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ stub _strtol_l diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 5058340e9c9..d7b9c943e51 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -891,7 +891,7 @@ # stub _strset_s @ cdecl _strtime(ptr) # stub _strtime_s -# stub _strtod_l +@ cdecl _strtod_l(str ptr ptr) MSVCRT_strtod_l @ cdecl _strtoi64(str ptr long) MSVCRT_strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) MSVCRT_strtoi64_l # stub _strtol_l diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index a241bab8552..830fe511b37 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -136,12 +136,72 @@ double CDECL MSVCRT_atof( const char *str ) return atof( str ); } +/********************************************************************* + * strtod_l (MSVCRT.@) + */ +double CDECL MSVCRT_strtod_l( const char *str, char **end, MSVCRT__locale_t locale) +{ + const char *p, *dec_point=NULL, *exp=NULL; + char *copy; + double ret; + int err = errno; + + if(!locale) + locale = get_locale(); + + if(!str) { + MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0); + *MSVCRT__errno() = MSVCRT_EINVAL; + return 0; + } + + /* FIXME: use *_l functions */ + p = str; + while(isspace(*p)) + p++; + if(*p=='+' || *p=='-') + p++; + while(isdigit(*p)) + p++; + if(*p == *locale->locinfo->lconv->decimal_point) { + if(*p!='.') + dec_point = p; + p++; + } + while(isdigit(*p)) + p++; + if(*p=='d' || *p=='D') + exp = p; + + /* FIXME: don't copy input string */ + if((dec_point || exp) && (copy=_strdup(str))) { + if(dec_point) + copy[dec_point-str] = '.'; + + if(exp) + copy[exp-str] = 'e'; + + ret = strtod(copy, end); + if(end) + *end = (char*)str+(*end-copy); + + MSVCRT_free(copy); + } else + ret = strtod(str, end); + + if(err != errno) + *MSVCRT__errno() = errno; + + return ret; + +} + /********************************************************************* * strtod (MSVCRT.@) */ double CDECL MSVCRT_strtod( const char *str, char **end ) { - return strtod( str, end ); + return MSVCRT_strtod_l( str, end, NULL ); } /********************************************************************* diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index c873d18edec..433a31817a7 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -1080,6 +1080,61 @@ static void test__strtoi64(void) ok(errno == ERANGE, "errno = %x\n", errno); } +static inline BOOL almost_equal(double d1, double d2) { + if(d1-d2>-1e-16 && d1-d2<1e-16) + return TRUE; + return FALSE; +} + +static void test__strtod(void) +{ + const char double1[] = "12.1"; + const char double2[] = "-13.721"; + const char double3[] = "INF"; + const char double4[] = ".21e12"; + const char double5[] = "214353e-3"; + + char *end; + double d; + + d = strtod(double1, &end); + ok(almost_equal(d, 12.1), "d = %lf\n", d); + ok(end == double1+4, "incorrect end (%d)\n", end-double1); + + d = strtod(double2, &end); + ok(almost_equal(d, -13.721), "d = %lf\n", d); + ok(end == double2+7, "incorrect end (%d)\n", end-double2); + + d = strtod(double3, &end); + todo_wine ok(almost_equal(d, 0), "d = %lf\n", d); + todo_wine ok(end == double3, "incorrect end (%d)\n", end-double3); + + d = strtod(double4, &end); + ok(almost_equal(d, 210000000000.0), "d = %lf\n", d); + ok(end == double4+6, "incorrect end (%d)\n", end-double4); + + d = strtod(double5, &end); + ok(almost_equal(d, 214.353), "d = %lf\n", d); + ok(end == double5+9, "incorrect end (%d)\n", end-double5); + + d = strtod("12.1d2", NULL); + ok(almost_equal(d, 12.1e2), "d = %lf\n", d); + + /* Set locale with non '.' decimal point (',') */ + if(!setlocale(LC_ALL, "Polish")) { + win_skip("system with limited locales\n"); + return; + } + + d = strtod("12.1", NULL); + todo_wine ok(almost_equal(d, 12.0), "d = %lf\n", d); + + d = strtod("12,1", NULL); + ok(almost_equal(d, 12.1), "d = %lf\n", d); + + setlocale(LC_ALL, "C"); +} + START_TEST(string) { char mem[100]; @@ -1133,4 +1188,5 @@ START_TEST(string) test_strtol(); test_strnlen(); test__strtoi64(); + test__strtod(); }