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