Andrew Eikum : jscript: Implement decodeURIComponent.

Alexandre Julliard julliard at winehq.org
Tue Nov 17 09:28:20 CST 2009


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

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon Nov 16 15:39:08 2009 -0600

jscript: Implement decodeURIComponent.

---

 dlls/jscript/global.c     |  120 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/jscript/tests/api.js |   20 ++++++++
 2 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c
index 8f6080d..501da79 100644
--- a/dlls/jscript/global.c
+++ b/dlls/jscript/global.c
@@ -930,11 +930,127 @@ static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    15.1.3.2 */
 static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    BSTR str, ret;
+    const WCHAR *ptr;
+    WCHAR *out_ptr;
+    DWORD len = 0;
+    HRESULT hres;
+
+    TRACE("\n");
+
+    if(!arg_cnt(dp)) {
+        if(retv) {
+            ret = SysAllocString(undefinedW);
+            if(!ret)
+                return E_OUTOFMEMORY;
+
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = ret;
+        }
+
+        return S_OK;
+    }
+
+    hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+    if(FAILED(hres))
+        return hres;
+
+    ptr = str;
+    while(*ptr) {
+        if(*ptr == '%') {
+            char octets[4];
+            unsigned char mask = 0x80;
+            int i, size, num_bytes = 0;
+            if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
+                FIXME("Throw URIError: Invalid hex sequence\n");
+                SysFreeString(str);
+                return E_FAIL;
+            }
+            octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
+            ptr += 3;
+            while(octets[0] & mask) {
+                mask = mask >> 1;
+                ++num_bytes;
+            }
+            if(num_bytes == 1 || num_bytes > 4) {
+                FIXME("Throw URIError: Invalid initial UTF character\n");
+                SysFreeString(str);
+                return E_FAIL;
+            }
+            for(i = 1; i < num_bytes; ++i) {
+                if(*ptr != '%'){
+                    FIXME("Throw URIError: Incomplete UTF sequence\n");
+                    SysFreeString(str);
+                    return E_FAIL;
+                }
+                if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
+                    FIXME("Throw URIError: Invalid hex sequence\n");
+                    SysFreeString(str);
+                    return E_FAIL;
+                }
+                octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
+                ptr += 3;
+            }
+            size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
+                    num_bytes ? num_bytes : 1, NULL, 0);
+            if(size == 0) {
+                FIXME("Throw URIError: Invalid UTF sequence\n");
+                SysFreeString(str);
+                return E_FAIL;
+            }
+            len += size;
+        }else {
+            ++ptr;
+            ++len;
+        }
+    }
+
+    out_ptr = ret = SysAllocStringLen(NULL, len);
+    if(!ret) {
+        SysFreeString(str);
+        return E_OUTOFMEMORY;
+    }
+
+    ptr = str;
+    while(*ptr) {
+        if(*ptr == '%') {
+            char octets[4];
+            unsigned char mask = 0x80;
+            int i, size, num_bytes = 0;
+            octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
+            ptr += 3;
+            while(octets[0] & mask) {
+                mask = mask >> 1;
+                ++num_bytes;
+            }
+            for(i = 1; i < num_bytes; ++i) {
+                octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
+                ptr += 3;
+            }
+            size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, octets,
+                    num_bytes ? num_bytes : 1, out_ptr, len);
+            len -= size;
+            out_ptr += size;
+        }else {
+            *out_ptr++ = *ptr++;
+            --len;
+        }
+    }
+
+    SysFreeString(str);
+
+    if(retv) {
+        V_VT(retv) = VT_BSTR;
+        V_BSTR(retv) = ret;
+    }else {
+        SysFreeString(ret);
+    }
+
+    return S_OK;
 }
 
 static const builtin_prop_t JSGlobal_props[] = {
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 1fb2f6d..42a79e8 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -60,24 +60,44 @@ ok(tmp === "abc", "encodeURI('abc') = " + tmp);
 
 tmp = encodeURIComponent("abc");
 ok(tmp === "abc", "encodeURIComponent('abc') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "abc", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("{abc}");
 ok(tmp === "%7Babc%7D", "encodeURIComponent('{abc}') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "{abc}", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("");
 ok(tmp === "", "encodeURIComponent('') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("\01\02\03\04");
 ok(tmp === "%01%02%03%04", "encodeURIComponent('\\01\\02\\03\\04') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "\01\02\03\04", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("{#@}");
 ok(tmp === "%7B%23%40%7D", "encodeURIComponent('{#@}') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "{#@}", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("\xa1 ");
 ok(tmp === "%C2%A1%20", "encodeURIComponent(\\xa1 ) = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "\xa1 ", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("\xffff");
 ok(tmp.length === 8, "encodeURIComponent('\\xffff').length = " + tmp.length);
+dec = decodeURIComponent(tmp);
+ok(dec === "\xffff", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent("abcABC123;/?:@&=+$,-_.!~*'()");
 ok(tmp === "abcABC123%3B%2F%3F%3A%40%26%3D%2B%24%2C-_.!~*'()", "encodeURIComponent('abcABC123;/?:@&=+$,-_.!~*'()') = " + tmp);
+dec = decodeURIComponent(tmp);
+ok(dec === "abcABC123;/?:@&=+$,-_.!~*'()", "decodeURIComponent('" + tmp + "') = " + dec);
 tmp = encodeURIComponent();
 ok(tmp === "undefined", "encodeURIComponent() = " + tmp);
 tmp = encodeURIComponent("abc", "test");
 ok(tmp === "abc", "encodeURIComponent('abc') = " + tmp);
+dec = decodeURIComponent();
+ok(dec === "undefined", "decodeURIComponent() = " + dec);
+dec = decodeURIComponent("abc", "test");
+ok(dec === "abc", "decodeURIComponent('abc') = " + dec);
 
 tmp = escape("abc");
 ok(tmp === "abc", "escape('abc') = " + tmp);




More information about the wine-cvs mailing list