Piotr Caban : jscript: Added $ handling to String.replace.

Alexandre Julliard julliard at winehq.org
Tue Aug 11 10:47:37 CDT 2009


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

Author: Piotr Caban <piotr.caban at gmail.com>
Date:   Tue Aug 11 14:06:52 2009 +0200

jscript: Added $ handling to String.replace.

---

 dlls/jscript/string.c        |   69 +++++++++++++++++++++++++++++++++++++----
 dlls/jscript/tests/regexp.js |   33 ++++++++++++++++++++
 2 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c
index 6695bf8..4cf3783 100644
--- a/dlls/jscript/string.c
+++ b/dlls/jscript/string.c
@@ -802,7 +802,7 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
     DWORD parens_cnt = 0, parens_size=0, rep_len=0, length;
     BSTR rep_str = NULL, match_str = NULL, ret_str, val_str = NULL;
     DispatchEx *rep_func = NULL, *regexp = NULL;
-    match_result_t *parens = NULL, match;
+    match_result_t *parens = NULL, match, **parens_ptr = &parens;
     strbuf_t ret = {NULL,0,0};
     BOOL gcheck = FALSE;
     VARIANT *arg_var;
@@ -884,12 +884,9 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
             if(FAILED(hres))
                 break;
 
-            if(strchrW(rep_str, '$')) {
-                FIXME("unsupported $ in replace string\n");
-                hres = E_NOTIMPL;
-            }
-
             rep_len = SysStringLen(rep_str);
+            if(!strchrW(rep_str, '$'))
+                parens_ptr = NULL;
         }
     }
 
@@ -900,7 +897,7 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
 
         while(1) {
             if(regexp) {
-                hres = regexp_match_next(regexp, gcheck, str, length, &cp, rep_func ? &parens : NULL,
+                hres = regexp_match_next(regexp, gcheck, str, length, &cp, parens_ptr,
                                          &parens_size, &parens_cnt, &match);
                 gcheck = TRUE;
 
@@ -934,6 +931,64 @@ static HRESULT String_replace(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
                 SysFreeString(cstr);
                 if(FAILED(hres))
                     break;
+            }else if(rep_str && regexp) {
+                const WCHAR *ptr = rep_str, *ptr2;
+
+                while((ptr2 = strchrW(ptr, '$'))) {
+                    hres = strbuf_append(&ret, ptr, ptr2-ptr);
+                    if(FAILED(hres))
+                        break;
+
+                    switch(ptr2[1]) {
+                    case '$':
+                        hres = strbuf_append(&ret, ptr2, 1);
+                        ptr = ptr2+2;
+                        break;
+                    case '&':
+                        hres = strbuf_append(&ret, match.str, match.len);
+                        ptr = ptr2+2;
+                        break;
+                    case '`':
+                        hres = strbuf_append(&ret, str, match.str-str);
+                        ptr = ptr2+2;
+                        break;
+                    case '\'':
+                        hres = strbuf_append(&ret, ecp, (str+length)-ecp);
+                        ptr = ptr2+2;
+                        break;
+                    default: {
+                        DWORD idx;
+
+                        if(!isdigitW(ptr2[1])) {
+                            hres = strbuf_append(&ret, ptr2, 1);
+                            ptr = ptr2+1;
+                            break;
+                        }
+
+                        idx = ptr2[1] - '0';
+                        if(isdigitW(ptr[3]) && idx*10 + (ptr[2]-'0') <= parens_cnt) {
+                            idx = idx*10 + (ptr[2]-'0');
+                            ptr = ptr2+3;
+                        }else if(idx && idx <= parens_cnt) {
+                            ptr = ptr2+2;
+                        }else {
+                            hres = strbuf_append(&ret, ptr2, 1);
+                            ptr = ptr2+1;
+                            break;
+                        }
+
+                        hres = strbuf_append(&ret, parens[idx-1].str, parens[idx-1].len);
+                    }
+                    }
+
+                    if(FAILED(hres))
+                        break;
+                }
+
+                if(SUCCEEDED(hres))
+                    hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr);
+                if(FAILED(hres))
+                    break;
             }else if(rep_str) {
                 hres = strbuf_append(&ret, rep_str, rep_len);
                 if(FAILED(hres))
diff --git a/dlls/jscript/tests/regexp.js b/dlls/jscript/tests/regexp.js
index 3e4db68..4344dfe 100644
--- a/dlls/jscript/tests/regexp.js
+++ b/dlls/jscript/tests/regexp.js
@@ -158,6 +158,39 @@ function replaceFunc2(m, subm, off, str) {
 r = "[test1] [test2]".replace(/\[([^\[]+)\]/g, replaceFunc2);
 ok(r === "r0 r1", "r = '" + r + "' expected 'r0 r1'");
 
+r = "$1,$2".replace(/(\$(\d))/g, "$$1-$1$2");
+ok(r === "$1-$11,$1-$22", "r = '" + r + "' expected '$1-$11,$1-$22'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$&");
+ok(r === "abc &1 123", "r = '" + r + "' expected 'abc &1 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$'");
+ok(r === "abc  123 123", "r = '" + r + "' expected 'abc  123 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$`");
+ok(r === "abc abc  123", "r = '" + r + "' expected 'abc abc  123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$3");
+ok(r === "abc $3 123", "r = '" + r + "' expected 'abc $3 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$");
+ok(r === "abc $ 123", "r = '" + r + "' expected 'abc $ 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$a");
+ok(r === "abc $a 123", "r = '" + r + "' expected 'abc $a 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$11");
+ok(r === "abc &11 123", "r = '" + r + "' expected 'abc &11 123'");
+
+r = "abc &1 123".replace(/(\&(\d))/g, "$0");
+ok(r === "abc $0 123", "r = '" + r + "' expected 'abc $0 123'");
+
+r = "1 2 3".replace("2", "$&");
+ok(r === "1 $& 3", "r = '" + r + "' expected '1 $& 3'");
+
+r = "1 2 3".replace("2", "$'");
+ok(r === "1 $' 3", "r = '" + r + "' expected '1 $' 3'");
+
 r = "1,,2,3".split(/,+/g);
 ok(r.length === 3, "r.length = " + r.length);
 ok(r[0] === "1", "r[0] = " + r[0]);




More information about the wine-cvs mailing list