From 91b798ddf802bb9d7e812d84df308a324f555652 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Sun, 21 Sep 2008 19:47:31 +0200 Subject: [PATCH] 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 deletion(-) diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index f368c3efca..6c0707dbd8 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 ed73202a5a..ba80154786 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 83732a2721..484d1920cc 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\""); -- 2.32.0.93.g670b81a890