Module: wine Branch: master Commit: 132009469c4f7f275b1b5deb1b48a11ace46373e URL: http://source.winehq.org/git/wine.git/?a=commit;h=132009469c4f7f275b1b5deb1b...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Aug 27 21:34:01 2009 +0200
jscript: Added RegExp.exec implementation.
---
dlls/jscript/regexp.c | 144 +++++++++++++++++++++++++++++++++++++++++- dlls/jscript/tests/regexp.js | 51 +++++++++++++++- 2 files changed, 192 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/regexp.c b/dlls/jscript/regexp.c index 754de36..5c473d4 100644 --- a/dlls/jscript/regexp.c +++ b/dlls/jscript/regexp.c @@ -3496,11 +3496,151 @@ static HRESULT RegExp_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPA return E_NOTIMPL; }
+static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_result_t *result, + const match_result_t *parens, DWORD parens_cnt, LCID lcid, jsexcept_t *ei, IDispatch **ret) +{ + DispatchEx *array; + VARIANT var; + int i; + HRESULT hres = S_OK; + + static const WCHAR indexW[] = {'i','n','d','e','x',0}; + static const WCHAR inputW[] = {'i','n','p','u','t',0}; + static const WCHAR zeroW[] = {'0',0}; + + hres = create_array(ctx, parens_cnt+1, &array); + if(FAILED(hres)) + return hres; + + for(i=0; i < parens_cnt; i++) { + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocStringLen(parens[i].str, parens[i].len); + if(!V_BSTR(&var)) { + hres = E_OUTOFMEMORY; + break; + } + + hres = jsdisp_propput_idx(array, i+1, lcid, &var, ei, NULL/*FIXME*/); + SysFreeString(V_BSTR(&var)); + if(FAILED(hres)) + break; + } + + while(SUCCEEDED(hres)) { + V_VT(&var) = VT_I4; + V_I4(&var) = result->str-input; + hres = jsdisp_propput_name(array, indexW, lcid, &var, ei, NULL/*FIXME*/); + if(FAILED(hres)) + break; + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = input; + hres = jsdisp_propput_name(array, inputW, lcid, &var, ei, NULL/*FIXME*/); + if(FAILED(hres)) + break; + + V_BSTR(&var) = SysAllocStringLen(result->str, result->len); + if(!V_BSTR(&var)) { + hres = E_OUTOFMEMORY; + break; + } + hres = jsdisp_propput_name(array, zeroW, lcid, &var, ei, NULL/*FIXME*/); + SysFreeString(V_BSTR(&var)); + break; + } + + if(FAILED(hres)) { + jsdisp_release(array); + return hres; + } + + *ret = (IDispatch*)_IDispatchEx_(array); + return S_OK; +} + +static HRESULT run_exec(DispatchEx *dispex, VARIANT *arg, LCID lcid, jsexcept_t *ei, BSTR *input, + match_result_t *match, match_result_t **parens, DWORD *parens_cnt, VARIANT_BOOL *ret) +{ + RegExpInstance *regexp; + DWORD parens_size = 0, last_index = 0, length; + const WCHAR *cp; + BSTR string; + HRESULT hres; + + if(!is_class(dispex, JSCLASS_REGEXP)) { + FIXME("Not a RegExp\n"); + return E_NOTIMPL; + } + + regexp = (RegExpInstance*)dispex; + + if(arg) { + hres = to_string(regexp->dispex.ctx, arg, ei, &string); + if(FAILED(hres)) + return hres; + }else { + string = SysAllocStringLen(NULL, 0); + if(!string) + return E_OUTOFMEMORY; + } + + length = SysStringLen(string); + if(regexp->jsregexp->flags & JSREG_GLOB) + last_index = regexp->last_index; + + cp = string + last_index; + hres = regexp_match_next(®exp->dispex, FALSE, string, length, &cp, parens, parens ? &parens_size : NULL, + parens_cnt, match); + if(FAILED(hres)) { + SysFreeString(string); + return hres; + } + + if(hres == S_OK) { + regexp->last_index = cp-string; + *ret = VARIANT_TRUE; + }else { + regexp->last_index = 0; + *ret = VARIANT_FALSE; + } + + if(input) + *input = string; + return S_OK; +} + static HRESULT RegExp_exec(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { - FIXME("\n"); - return E_NOTIMPL; + match_result_t *parens = NULL, match; + DWORD parens_cnt = 0; + VARIANT_BOOL b; + BSTR string; + HRESULT hres; + + TRACE("\n"); + + hres = run_exec(dispex, arg_cnt(dp) ? get_arg(dp,0) : NULL, lcid, ei, &string, &match, &parens, &parens_cnt, &b); + if(FAILED(hres)) + return hres; + + if(retv) { + if(b) { + IDispatch *ret; + + hres = create_match_array(dispex->ctx, string, &match, parens, parens_cnt, lcid, ei, &ret); + if(SUCCEEDED(hres)) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = ret; + } + }else { + V_VT(retv) = VT_NULL; + } + } + + heap_free(parens); + SysFreeString(string); + return hres; }
static HRESULT RegExp_test(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, diff --git a/dlls/jscript/tests/regexp.js b/dlls/jscript/tests/regexp.js index b246284..27c1afb 100644 --- a/dlls/jscript/tests/regexp.js +++ b/dlls/jscript/tests/regexp.js @@ -17,11 +17,60 @@ */
-var m, re; +var m, re, b;
re = /a+/; ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
+m = re.exec(" aabaaa"); +ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex); +ok(m.index === 1, "m.index = " + m.index); +ok(m.input === " aabaaa", "m.input = " + m.input); +ok(m.length === 1, "m.length = " + m.length); +ok(m[0] === "aa", "m[0] = " + m[0]); + +m = re.exec(" aabaaa"); +ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex); +ok(m.index === 1, "m.index = " + m.index); +ok(m.input === " aabaaa", "m.input = " + m.input); +ok(m.length === 1, "m.length = " + m.length); +ok(m[0] === "aa", "m[0] = " + m[0]); + +re = /a+/g; +ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex); + +m = re.exec(" aabaaa"); +ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex); +ok(m.index === 1, "m.index = " + m.index); +ok(m.input === " aabaaa", "m.input = " + m.input); +ok(m.length === 1, "m.length = " + m.length); +ok(m[0] === "aa", "m[0] = " + m[0]); + +m = re.exec(" aabaaa"); +ok(re.lastIndex === 7, "re.lastIndex = " + re.lastIndex); +ok(m.index === 4, "m.index = " + m.index); +ok(m.input === " aabaaa", "m.input = " + m.input); +ok(m.length === 1, "m.length = " + m.length); +ok(m[0] === "aaa", "m[0] = " + m[0]); + +m = re.exec(" aabaaa"); +ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex); +ok(m === null, "m is not null"); + +re.exec(" a"); +ok(re.lastIndex === 16, "re.lastIndex = " + re.lastIndex); + +m = re.exec(" a"); +ok(m === null, "m is not null"); +ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex); + +m = re.exec(" a"); +ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex); + +m = re.exec(); +ok(m === null, "m is not null"); +ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex); + m = "abcabc".match(/ca/); ok(typeof(m) === "object", "typeof m is not object"); ok(m.length === 1, "m.length is not 1");