>From b686aa26552a0ba073ced0a474fcad1d7910285b Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Wed, 16 Oct 2019 15:03:23 +0800 Subject: [PATCH 04/10] vbscript: Implement IRegExp2::Replace(). Content-Type: text/plain; charset=UTF-8 To: wine-devel@winehq.org Signed-off-by: Dmitry Timoshkov --- dlls/vbscript/tests/vbscript.c | 2 - dlls/vbscript/vbregexp.c | 89 +++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/dlls/vbscript/tests/vbscript.c b/dlls/vbscript/tests/vbscript.c index d0763d416f..fdbfc4465b 100644 --- a/dlls/vbscript/tests/vbscript.c +++ b/dlls/vbscript/tests/vbscript.c @@ -1178,10 +1178,8 @@ static void test_RegExp_Replace(void) V_VT(&var) = VT_BSTR; V_BSTR(&var) = a2bstr(test[i].replace); hr = IRegExp2_Replace(regexp, str, var, &ret); -todo_wine ok(hr == S_OK, "got %#x\n", hr); result = a2bstr(test[i].result); -if (hr == S_OK) ok(!wcscmp(ret, result), "got %s, expected %s\n", wine_dbgstr_w(ret), wine_dbgstr_w(result)); SysFreeString(result); SysFreeString(ret); diff --git a/dlls/vbscript/vbregexp.c b/dlls/vbscript/vbregexp.c index 3400e81066..74a54bc710 100644 --- a/dlls/vbscript/vbregexp.c +++ b/dlls/vbscript/vbregexp.c @@ -1,5 +1,6 @@ /* * Copyright 2013 Piotr Caban for CodeWeavers + * Copyright 2019 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1432,13 +1433,97 @@ static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_B return hres; } +static HRESULT bstrcat(BSTR *str, const WCHAR *append, unsigned int len) +{ + unsigned int old_len = SysStringLen(*str); + + if (!SysReAllocStringLen(str, NULL, old_len + len)) + return E_OUTOFMEMORY; + + memcpy(*str + old_len, append, len * sizeof(WCHAR)); + return S_OK; +} + static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString, VARIANT replaceVar, BSTR *pDestString) { RegExp2 *This = impl_from_IRegExp2(iface); - FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString), + match_state_t *result; + const WCHAR *pos; + BSTR ret; + HRESULT hres; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString), debugstr_variant(&replaceVar), pDestString); - return E_NOTIMPL; + + if(!This->pattern) { + FIXME("NULL pattern\n"); + return E_NOTIMPL; + } + + if(!This->regexp) { + This->regexp = regexp_new(NULL, &This->pool, This->pattern, + lstrlenW(This->pattern), This->flags, FALSE); + if(!This->regexp) + return E_FAIL; + }else { + hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags); + if(FAILED(hres)) + return hres; + } + + ret = SysAllocString(L""); + if(!ret) + return E_OUTOFMEMORY; + + pos = sourceString; + while(1) { + result = alloc_match_state(This->regexp, NULL, pos); + if(!result) { + hres = E_OUTOFMEMORY; + break; + } + + hres = regexp_execute(This->regexp, NULL, &This->pool, + sourceString, SysStringLen(sourceString), result); + if(hres != S_OK) { + heap_free(result); + break; + } + + /* add part of original string */ + hres = bstrcat(&ret, pos, result->cp - result->match_len - pos); + if(hres != S_OK) { + heap_free(result); + break; + } + + pos = result->cp; + + /* add replacement */ + hres = bstrcat(&ret, V_BSTR(&replaceVar), SysStringLen(V_BSTR(&replaceVar))); + heap_free(result); + if(hres != S_OK) + break; + + if(!(This->flags & REG_GLOB)) + break; + } + + if(FAILED(hres)) { + SysFreeString(ret); + return hres; + } + + /* add remainder */ + hres = bstrcat(&ret, pos, SysStringLen(sourceString) - (pos - sourceString)); + if(FAILED(hres)) { + SysFreeString(ret); + return hres; + } + + *pDestString = ret; + return S_OK; } static const IRegExp2Vtbl RegExp2Vtbl = { -- 2.20.1