msvcrt: Added _strtod_l implementation.
This commit is contained in:
parent
776998866a
commit
94112ff960
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue