Jacek Caban : jscript: Added RegExp.exec implementation.

Alexandre Julliard julliard at winehq.org
Fri Aug 28 10:17:46 CDT 2009


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

Author: Jacek Caban <jacek at 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(&regexp->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");




More information about the wine-cvs mailing list