Jacek Caban : jscript: Added string to number conversion implementation.

Alexandre Julliard julliard at winehq.org
Mon Sep 22 07:03:59 CDT 2008


Module: wine
Branch: master
Commit: 91b798ddf802bb9d7e812d84df308a324f555652
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=91b798ddf802bb9d7e812d84df308a324f555652

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Sun Sep 21 19:47:31 2008 +0200

jscript: Added string to number conversion implementation.

---

 dlls/jscript/jsutils.c     |  106 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/jscript/lex.c         |    2 +-
 dlls/jscript/tests/lang.js |    5 ++
 3 files changed, 112 insertions(+), 1 deletions(-)

diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index f368c3e..6c0707d 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -217,6 +217,110 @@ HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
     return S_OK;
 }
 
+static int hex_to_int(WCHAR c)
+{
+    if('0' <= c && c <= '9')
+        return c-'0';
+
+    if('a' <= c && c <= 'f')
+        return c-'a'+10;
+
+    if('A' <= c && c <= 'F')
+        return c-'A'+10;
+
+    return -1;
+}
+
+/* ECMA-262 3rd Edition    9.3.1 */
+static HRESULT str_to_number(BSTR str, VARIANT *ret)
+{
+    const WCHAR *ptr = str;
+    BOOL neg = FALSE;
+    DOUBLE d = 0.0;
+
+    static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
+
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(!strncmpW(ptr, infinityW, sizeof(infinityW)/sizeof(WCHAR))) {
+        ptr += sizeof(infinityW)/sizeof(WCHAR);
+        while(*ptr && isspaceW(*ptr))
+            ptr++;
+
+        if(*ptr) {
+            FIXME("NaN\n");
+            return E_NOTIMPL;
+        }
+
+        FIXME("inf\n");
+        return E_NOTIMPL;
+    }
+
+    if(*ptr == '-') {
+        neg = TRUE;
+        ptr++;
+    }else if(*ptr == '+') {
+        ptr++;
+    }else if(*ptr == '0' && ptr[1] == 'x') {
+        DWORD l = 0;
+
+        ptr += 2;
+        while((l = hex_to_int(*ptr)) != -1) {
+            d = d*16 + l;
+            ptr++;
+        }
+
+        num_set_val(ret, d);
+        return S_OK;
+    }
+
+    while(isdigitW(*ptr))
+        d = d*10 + (*ptr++ - '0');
+
+    if(*ptr == 'e' || *ptr == 'E') {
+        BOOL eneg = FALSE;
+        LONG l = 0;
+
+        ptr++;
+        if(*ptr == '-') {
+            ptr++;
+            eneg = TRUE;
+        }else if(*ptr == '+') {
+            ptr++;
+        }
+
+        while(isdigitW(*ptr))
+            l = l*10 + (*ptr++ - '0');
+        if(eneg)
+            l = -l;
+
+        d *= pow(10, l);
+    }else if(*ptr == '.') {
+        DOUBLE dec = 0.1;
+
+        ptr++;
+        while(isdigitW(*ptr)) {
+            d += dec * (*ptr++ - '0');
+            dec *= 0.1;
+        }
+    }
+
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(*ptr) {
+        FIXME("NaN\n");
+        return E_NOTIMPL;
+    }
+
+    if(neg)
+        d = -d;
+
+    num_set_val(ret, d);
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    9.3 */
 HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
 {
@@ -229,6 +333,8 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
     case VT_R8:
         *ret = *v;
         break;
+    case VT_BSTR:
+        return str_to_number(V_BSTR(v), ret);
     case VT_BOOL:
         V_VT(ret) = VT_I4;
         V_I4(ret) = V_BOOL(v) ? 1 : 0;
diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c
index ed73202..ba80154 100644
--- a/dlls/jscript/lex.c
+++ b/dlls/jscript/lex.c
@@ -387,7 +387,7 @@ static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **li
             e = e*10 + *ctx->ptr++ - '0';
         e *= sign;
 
-        d = pow(d, e);
+        d *= pow(10, e);
     }
 
     *literal = parser_alloc(ctx, sizeof(literal_t));
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 83732a2..484d192 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -344,6 +344,11 @@ ok(+3 === 3, "+3 !== 3");
 ok(+true === 1, "+true !== 1");
 ok(+false === 0, "+false !== 0");
 ok(+null === 0, "+null !== 0");
+ok(+"0" === 0, "+'0' !== 0");
+ok(+"3" === 3, "+'3' !== 3");
+ok(+"-3" === -3, "+'-3' !== -3");
+ok(+"0xff" === 255, "+'0xff' !== 255");
+ok(+"3e3" === 3000, "+'3e3' !== 3000");
 
 ok("" + 0 === "0", "\"\" + 0 !== \"0\"");
 ok("" + 123 === "123", "\"\" + 123 !== \"123\"");




More information about the wine-cvs mailing list