Erich E. Hoover : msvcrt: Use parse_double for wcstod.

Alexandre Julliard julliard at winehq.org
Thu Jan 2 16:04:21 CST 2020


Module: wine
Branch: master
Commit: 66c9c358ae5c50fc246cf4a4e280b401a5fc730b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=66c9c358ae5c50fc246cf4a4e280b401a5fc730b

Author: Erich E. Hoover <erich.e.hoover at gmail.com>
Date:   Tue Dec 31 16:00:11 2019 -0700

msvcrt: Use parse_double for wcstod.

Signed-off-by: Erich E. Hoover <erich.e.hoover at gmail.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/msvcrt.h |   1 +
 dlls/msvcrt/wcs.c    | 130 ++++++++-------------------------------------------
 2 files changed, 20 insertions(+), 111 deletions(-)

diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 84e3b013bc..244df7d23c 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -1073,6 +1073,7 @@ int __cdecl      MSVCRT_iswdigit(MSVCRT_wint_t);
 int __cdecl      MSVCRT_isleadbyte(int);
 int __cdecl      MSVCRT__isleadbyte_l(int, MSVCRT__locale_t);
 int __cdecl      MSVCRT__isspace_l(int, MSVCRT__locale_t);
+int __cdecl      MSVCRT__iswspace_l(MSVCRT_wchar_t, MSVCRT__locale_t);
 
 void __cdecl     MSVCRT__lock_file(MSVCRT_FILE*);
 void __cdecl     MSVCRT__unlock_file(MSVCRT_FILE*);
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 6d03997d9e..1abe28b7d9 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -381,15 +381,17 @@ int CDECL MSVCRT__wcsncoll(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str
     return MSVCRT__wcsncoll_l(str1, str2, count, NULL);
 }
 
-static double MSVCRT_mul_pow10(double x, int exp)
+static MSVCRT_wchar_t strtod_wstr_get(void *ctx)
 {
-    BOOL negexp = (exp < 0);
-    double ret;
+    const MSVCRT_wchar_t **p = ctx;
+    if (!**p) return MSVCRT_WEOF;
+    return *(*p)++;
+}
 
-    if(negexp)
-        exp = -exp;
-    ret = pow(10.0, exp);
-    return (negexp ? x/ret : x*ret);
+static void strtod_wstr_unget(void *ctx)
+{
+    const MSVCRT_wchar_t **p = ctx;
+    (*p)--;
 }
 
 /*********************************************************************
@@ -398,121 +400,27 @@ static double MSVCRT_mul_pow10(double x, int exp)
 double CDECL MSVCRT__wcstod_l(const MSVCRT_wchar_t* str, MSVCRT_wchar_t** end,
         MSVCRT__locale_t locale)
 {
-    int exp1=0, exp2=0, exp3=0, sign=1;
     MSVCRT_pthreadlocinfo locinfo;
-    unsigned __int64 d=0, hlp;
-    BOOL found_digit = FALSE;
-    unsigned fpcontrol;
-    const MSVCRT_wchar_t *p;
+    const MSVCRT_wchar_t *beg, *p;
     double ret;
 
-    if (!MSVCRT_CHECK_PMT(str != NULL)) return 0;
+    if (!MSVCRT_CHECK_PMT(str != NULL)) {
+        if (end) *end = NULL;
+        return 0;
+    }
 
-    if(!locale)
+    if (!locale)
         locinfo = get_locinfo();
     else
         locinfo = locale->locinfo;
 
     p = str;
-    while(isspaceW(*p))
-        p++;
-
-    if(*p == '-') {
-        sign = -1;
-        p++;
-    } else  if(*p == '+')
-        p++;
-
-    while(*p>='0' && *p<='9') {
-        found_digit = TRUE;
-        hlp = d*10+*(p++)-'0';
-        if(d>MSVCRT_UI64_MAX/10 || hlp<d) {
-            exp1++;
-            break;
-        } else
-            d = hlp;
-    }
-    while(*p>='0' && *p<='9') {
-        exp1++;
-        p++;
-    }
-    if(*p == *locinfo->lconv->decimal_point)
+    while(MSVCRT__iswspace_l(*p, locale))
         p++;
+    beg = p;
 
-    while(*p>='0' && *p<='9') {
-        found_digit = TRUE;
-        hlp = d*10+*(p++)-'0';
-        if(d>MSVCRT_UI64_MAX/10 || hlp<d)
-            break;
-
-        d = hlp;
-        exp1--;
-    }
-    while(*p>='0' && *p<='9')
-        p++;
-
-    if(!found_digit) {
-        if(end)
-            *end = (MSVCRT_wchar_t*)str;
-        return 0.0;
-    }
-
-    if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
-        int e=0, s=1;
-
-        p++;
-        if(*p == '-') {
-            s = -1;
-            p++;
-        } else if(*p == '+')
-            p++;
-
-        if(*p>='0' && *p<='9') {
-            while(*p>='0' && *p<='9') {
-                if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
-                    e = INT_MAX;
-                p++;
-            }
-            e *= s;
-
-            if(exp1<0 && e<0 && exp1+e>=0) exp1 = INT_MIN;
-            else if(exp1>0 && e>0 && exp1+e<0) exp1 = INT_MAX;
-            else exp3 += e;
-        } else {
-            if(*p=='-' || *p=='+')
-                p--;
-            p--;
-        }
-    }
-
-    fpcontrol = _control87(0, 0);
-    _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
-               |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT|MSVCRT__PC_64,
-               MSVCRT__MCW_EM | MSVCRT__MCW_PC );
-
-    /* take the number without exponent and convert it into a double */
-    ret = MSVCRT_mul_pow10(d, exp1);
-    /* shift the number to the representation where the first non-zero digit is in the ones place */
-    exp2 = (ret != 0.0 ? (int)round(log10(ret)) : 0);
-    if (exp3-exp2 >= MSVCRT_FLT_MIN_10_EXP && exp3-exp2 <= MSVCRT_FLT_MAX_10_EXP)
-        exp2 = 0; /* only bother to take this extra step with very small or very large numbers */
-    /* incorporate an additional shift to deal with floating point denormal values (if necessary) */
-    if(exp3-exp2 < MSVCRT_DBL_MIN_10_EXP)
-        exp2 += exp3-exp2-MSVCRT_DBL_MIN_10_EXP;
-    ret = MSVCRT_mul_pow10(ret, exp2);
-    /* apply the exponent (and undo any shift) */
-    ret = MSVCRT_mul_pow10(ret, exp3-exp2);
-    /* apply the sign bit */
-    ret *= sign;
-
-    _control87( fpcontrol, MSVCRT__MCW_EM | MSVCRT__MCW_PC );
-
-    if((d && ret==0.0) || isinf(ret))
-        *MSVCRT__errno() = MSVCRT_ERANGE;
-
-    if(end)
-        *end = (MSVCRT_wchar_t*)p;
-
+    ret = parse_double(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, NULL);
+    if (end) *end = (p == beg ? (MSVCRT_wchar_t*)str : (MSVCRT_wchar_t*)p);
     return ret;
 }
 




More information about the wine-cvs mailing list