jscript: Avoid copying regular expression results.
This commit is contained in:
parent
67c7cc5517
commit
f16c9877bd
|
@ -442,8 +442,10 @@ HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN;
|
||||||
#define REM_CHECK_GLOBAL 0x0001
|
#define REM_CHECK_GLOBAL 0x0001
|
||||||
#define REM_RESET_INDEX 0x0002
|
#define REM_RESET_INDEX 0x0002
|
||||||
#define REM_NO_CTX_UPDATE 0x0004
|
#define REM_NO_CTX_UPDATE 0x0004
|
||||||
HRESULT regexp_match_next(script_ctx_t*,jsdisp_t*,DWORD,jsstr_t*,const WCHAR**,match_result_t**,
|
#define REM_ALLOC_RESULT 0x0008
|
||||||
DWORD*,DWORD*,match_result_t*) DECLSPEC_HIDDEN;
|
#define REM_NO_PARENS 0x0010
|
||||||
|
struct match_state_t;
|
||||||
|
HRESULT regexp_match_next(script_ctx_t*,jsdisp_t*,DWORD,jsstr_t*,struct match_state_t**) DECLSPEC_HIDDEN;
|
||||||
HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*) DECLSPEC_HIDDEN;
|
HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*) DECLSPEC_HIDDEN;
|
||||||
HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_HIDDEN;
|
HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
|
@ -73,19 +73,13 @@ static void set_last_index(RegExpInstance *This, DWORD last_index)
|
||||||
This->last_index_val = jsval_number(last_index);
|
This->last_index_val = jsval_number(last_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, DWORD rem_flags,
|
static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
|
||||||
jsstr_t *str, const WCHAR **cp, match_result_t **parens, DWORD *parens_size,
|
DWORD rem_flags, jsstr_t *str, match_state_t *ret)
|
||||||
DWORD *parens_cnt, match_result_t *ret)
|
|
||||||
{
|
{
|
||||||
match_state_t *result;
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
result = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, *cp);
|
|
||||||
if(!result)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap,
|
hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap,
|
||||||
str->str, jsstr_length(str), result);
|
str->str, jsstr_length(str), ret);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
if(hres == S_FALSE) {
|
if(hres == S_FALSE) {
|
||||||
|
@ -93,55 +87,22 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, D
|
||||||
set_last_index(regexp, 0);
|
set_last_index(regexp, 0);
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
*cp = result->cp;
|
|
||||||
|
|
||||||
if(parens) {
|
|
||||||
if(result->paren_count > *parens_size) {
|
|
||||||
match_result_t *new_parens;
|
|
||||||
|
|
||||||
if(*parens)
|
|
||||||
new_parens = heap_realloc(*parens, sizeof(match_result_t)*result->paren_count);
|
|
||||||
else
|
|
||||||
new_parens = heap_alloc(sizeof(match_result_t)*result->paren_count);
|
|
||||||
if(!new_parens)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
*parens_size = result->paren_count;
|
|
||||||
*parens = new_parens;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) {
|
if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) {
|
||||||
jsstr_release(ctx->last_match);
|
jsstr_release(ctx->last_match);
|
||||||
ctx->last_match = jsstr_addref(str);
|
ctx->last_match = jsstr_addref(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parens) {
|
|
||||||
DWORD i;
|
|
||||||
|
|
||||||
*parens_cnt = result->paren_count;
|
|
||||||
|
|
||||||
for(i=0; i < result->paren_count; i++) {
|
|
||||||
if(result->parens[i].index == -1) {
|
|
||||||
(*parens)[i].str = NULL;
|
|
||||||
(*parens)[i].len = 0;
|
|
||||||
}else {
|
|
||||||
(*parens)[i].str = str->str + result->parens[i].index;
|
|
||||||
(*parens)[i].len = result->parens[i].length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
|
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
|
||||||
DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), result->paren_count);
|
DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), ret->paren_count);
|
||||||
|
|
||||||
for(i=0; i < n; i++) {
|
for(i=0; i < n; i++) {
|
||||||
if(result->parens[i].index == -1) {
|
if(ret->parens[i].index == -1) {
|
||||||
ctx->match_parens[i].str = NULL;
|
ctx->match_parens[i].str = NULL;
|
||||||
ctx->match_parens[i].len = 0;
|
ctx->match_parens[i].len = 0;
|
||||||
}else {
|
}else {
|
||||||
ctx->match_parens[i].str = ctx->last_match->str + result->parens[i].index;
|
ctx->match_parens[i].str = ctx->last_match->str + ret->parens[i].index;
|
||||||
ctx->match_parens[i].len = result->parens[i].length;
|
ctx->match_parens[i].len = ret->parens[i].length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,34 +110,65 @@ static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, D
|
||||||
memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
|
memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->str = result->cp - result->match_len;
|
set_last_index(regexp, ret->cp-str->str);
|
||||||
ret->len = result->match_len;
|
|
||||||
set_last_index(regexp, result->cp-str->str);
|
|
||||||
|
|
||||||
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
|
if(!(rem_flags & REM_NO_CTX_UPDATE)) {
|
||||||
ctx->last_match_index = ret->str-str->str;
|
ctx->last_match_index = ret->cp-str->str-ret->match_len;
|
||||||
ctx->last_match_length = result->match_len;
|
ctx->last_match_length = ret->match_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex, DWORD rem_flags, jsstr_t *str,
|
HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
|
||||||
const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt,
|
DWORD rem_flags, jsstr_t *str, match_state_t **ret)
|
||||||
match_result_t *ret)
|
|
||||||
{
|
{
|
||||||
RegExpInstance *regexp = (RegExpInstance*)dispex;
|
RegExpInstance *regexp = (RegExpInstance*)dispex;
|
||||||
|
match_state_t *match;
|
||||||
heap_pool_t *mark;
|
heap_pool_t *mark;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB))
|
if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB)) {
|
||||||
|
if(rem_flags & REM_ALLOC_RESULT)
|
||||||
|
*ret = NULL;
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rem_flags & REM_ALLOC_RESULT) {
|
||||||
|
match = alloc_match_state(regexp->jsregexp, NULL, str->str);
|
||||||
|
if(!match)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
*ret = match;
|
||||||
|
}
|
||||||
|
|
||||||
mark = heap_pool_mark(&ctx->tmp_heap);
|
mark = heap_pool_mark(&ctx->tmp_heap);
|
||||||
|
|
||||||
hres = do_regexp_match_next(ctx, regexp, rem_flags, str, cp, parens, parens_size, parens_cnt, ret);
|
if(rem_flags & REM_NO_PARENS) {
|
||||||
|
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, NULL);
|
||||||
|
if(!match) {
|
||||||
|
heap_pool_clear(mark);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
match->cp = (*ret)->cp;
|
||||||
|
match->match_len = (*ret)->match_len;
|
||||||
|
}else {
|
||||||
|
match = *ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = do_regexp_match_next(ctx, regexp, rem_flags, str, match);
|
||||||
|
|
||||||
|
if(rem_flags & REM_NO_PARENS) {
|
||||||
|
(*ret)->cp = match->cp;
|
||||||
|
(*ret)->match_len = match->match_len;
|
||||||
|
}
|
||||||
|
|
||||||
heap_pool_clear(mark);
|
heap_pool_clear(mark);
|
||||||
|
|
||||||
|
if(hres != S_OK && (rem_flags & REM_ALLOC_RESULT)) {
|
||||||
|
heap_free(match);
|
||||||
|
*ret = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,16 +176,22 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
|
||||||
match_result_t **match_result, DWORD *result_cnt)
|
match_result_t **match_result, DWORD *result_cnt)
|
||||||
{
|
{
|
||||||
RegExpInstance *This = (RegExpInstance*)dispex;
|
RegExpInstance *This = (RegExpInstance*)dispex;
|
||||||
match_result_t *ret = NULL, cres;
|
match_result_t *ret = NULL;
|
||||||
const WCHAR *cp = str->str;
|
match_state_t *result;
|
||||||
DWORD i=0, ret_size = 0;
|
DWORD i=0, ret_size = 0;
|
||||||
heap_pool_t *mark;
|
heap_pool_t *mark;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
mark = heap_pool_mark(&ctx->tmp_heap);
|
mark = heap_pool_mark(&ctx->tmp_heap);
|
||||||
|
|
||||||
|
result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str->str);
|
||||||
|
if(!result) {
|
||||||
|
heap_pool_clear(mark);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
hres = do_regexp_match_next(ctx, This, 0, str, &cp, NULL, NULL, NULL, &cres);
|
hres = do_regexp_match_next(ctx, This, 0, str, result);
|
||||||
if(hres == S_FALSE) {
|
if(hres == S_FALSE) {
|
||||||
hres = S_OK;
|
hres = S_OK;
|
||||||
break;
|
break;
|
||||||
|
@ -218,7 +216,8 @@ static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret[i++] = cres;
|
ret[i].str = result->cp - result->match_len;
|
||||||
|
ret[i++].len = result->match_len;
|
||||||
|
|
||||||
if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
|
if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
|
||||||
hres = S_OK;
|
hres = S_OK;
|
||||||
|
@ -329,8 +328,8 @@ static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match_result_t *result,
|
static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
|
||||||
const match_result_t *parens, DWORD parens_cnt, IDispatch **ret)
|
const match_state_t *result, IDispatch **ret)
|
||||||
{
|
{
|
||||||
jsdisp_t *array;
|
jsdisp_t *array;
|
||||||
jsstr_t *str;
|
jsstr_t *str;
|
||||||
|
@ -342,12 +341,15 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match
|
||||||
static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
|
static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
|
||||||
static const WCHAR zeroW[] = {'0',0};
|
static const WCHAR zeroW[] = {'0',0};
|
||||||
|
|
||||||
hres = create_array(ctx, parens_cnt+1, &array);
|
hres = create_array(ctx, result->paren_count+1, &array);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
for(i=0; i < parens_cnt; i++) {
|
for(i=0; i < result->paren_count; i++) {
|
||||||
str = jsstr_alloc_len(parens[i].str, parens[i].len);
|
if(result->parens[i].index == -1)
|
||||||
|
str = jsstr_empty();
|
||||||
|
else
|
||||||
|
str = jsstr_alloc_len(input->str+result->parens[i].index, result->parens[i].length);
|
||||||
if(!str) {
|
if(!str) {
|
||||||
hres = E_OUTOFMEMORY;
|
hres = E_OUTOFMEMORY;
|
||||||
break;
|
break;
|
||||||
|
@ -360,11 +362,11 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match
|
||||||
}
|
}
|
||||||
|
|
||||||
while(SUCCEEDED(hres)) {
|
while(SUCCEEDED(hres)) {
|
||||||
hres = jsdisp_propput_name(array, indexW, jsval_number(result->str-input->str));
|
hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len));
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->str-input->str+result->len));
|
hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str));
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -372,7 +374,7 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
str = jsstr_alloc_len(result->str, result->len);
|
str = jsstr_alloc_len(result->cp-result->match_len, result->match_len);
|
||||||
if(!str) {
|
if(!str) {
|
||||||
hres = E_OUTOFMEMORY;
|
hres = E_OUTOFMEMORY;
|
||||||
break;
|
break;
|
||||||
|
@ -391,12 +393,12 @@ static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input, const match
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t **input,
|
static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
|
||||||
match_result_t *match, match_result_t **parens, DWORD *parens_cnt, BOOL *ret)
|
jsstr_t **input, match_state_t **result, BOOL *ret)
|
||||||
{
|
{
|
||||||
RegExpInstance *regexp;
|
RegExpInstance *regexp;
|
||||||
DWORD parens_size = 0, last_index = 0;
|
match_state_t *match;
|
||||||
const WCHAR *cp;
|
DWORD last_index = 0;
|
||||||
jsstr_t *string;
|
jsstr_t *string;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
|
@ -424,14 +426,19 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t
|
||||||
last_index = regexp->last_index;
|
last_index = regexp->last_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = string->str + last_index;
|
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string->str+last_index);
|
||||||
hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, &cp, parens,
|
if(!match) {
|
||||||
parens ? &parens_size : NULL, parens_cnt, match);
|
jsstr_release(string);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, &match);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
jsstr_release(string);
|
jsstr_release(string);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*result = match;
|
||||||
*ret = hres == S_OK;
|
*ret = hres == S_OK;
|
||||||
if(input)
|
if(input)
|
||||||
*input = string;
|
*input = string;
|
||||||
|
@ -443,17 +450,19 @@ static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg, jsstr_t
|
||||||
static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
match_result_t *parens = NULL, match;
|
match_state_t *match;
|
||||||
DWORD parens_cnt = 0;
|
heap_pool_t *mark;
|
||||||
BOOL b;
|
BOOL b;
|
||||||
jsstr_t *string;
|
jsstr_t *string;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &parens, &parens_cnt, &b);
|
mark = heap_pool_mark(&ctx->tmp_heap);
|
||||||
|
|
||||||
|
hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
heap_free(parens);
|
heap_pool_clear(mark);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +470,7 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig
|
||||||
if(b) {
|
if(b) {
|
||||||
IDispatch *ret;
|
IDispatch *ret;
|
||||||
|
|
||||||
hres = create_match_array(ctx, string, &match, parens, parens_cnt, &ret);
|
hres = create_match_array(ctx, string, match, &ret);
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres))
|
||||||
*r = jsval_disp(ret);
|
*r = jsval_disp(ret);
|
||||||
}else {
|
}else {
|
||||||
|
@ -469,7 +478,7 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_free(parens);
|
heap_pool_clear(mark);
|
||||||
jsstr_release(string);
|
jsstr_release(string);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
@ -477,7 +486,8 @@ static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig
|
||||||
static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
match_result_t match;
|
match_state_t *match;
|
||||||
|
heap_pool_t *mark;
|
||||||
jsstr_t *undef_str;
|
jsstr_t *undef_str;
|
||||||
BOOL b;
|
BOOL b;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
@ -490,7 +500,9 @@ static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsig
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str), NULL, &match, NULL, NULL, &b);
|
mark = heap_pool_mark(&ctx->tmp_heap);
|
||||||
|
hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str), NULL, &match, &b);
|
||||||
|
heap_pool_clear(mark);
|
||||||
if(!argc)
|
if(!argc)
|
||||||
jsstr_release(undef_str);
|
jsstr_release(undef_str);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
|
@ -673,13 +685,19 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
if(!(regexp->jsregexp->flags & REG_GLOB)) {
|
if(!(regexp->jsregexp->flags & REG_GLOB)) {
|
||||||
match_result_t match, *parens = NULL;
|
match_state_t *match;
|
||||||
DWORD parens_cnt, parens_size = 0;
|
heap_pool_t *mark;
|
||||||
const WCHAR *cp = str->str;
|
|
||||||
|
|
||||||
hres = regexp_match_next(ctx, ®exp->dispex, 0, str, &cp, &parens, &parens_size, &parens_cnt, &match);
|
mark = heap_pool_mark(&ctx->tmp_heap);
|
||||||
|
match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, str->str);
|
||||||
|
if(!match) {
|
||||||
|
heap_pool_clear(mark);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = regexp_match_next(ctx, ®exp->dispex, 0, str, &match);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres)) {
|
||||||
heap_free(parens);
|
heap_pool_clear(mark);
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +705,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
|
||||||
if(hres == S_OK) {
|
if(hres == S_OK) {
|
||||||
IDispatch *ret;
|
IDispatch *ret;
|
||||||
|
|
||||||
hres = create_match_array(ctx, str, &match, parens, parens_cnt, &ret);
|
hres = create_match_array(ctx, str, match, &ret);
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres))
|
||||||
*r = jsval_disp(ret);
|
*r = jsval_disp(ret);
|
||||||
}else {
|
}else {
|
||||||
|
@ -695,7 +713,7 @@ HRESULT regexp_string_match(script_ctx_t *ctx, jsdisp_t *re, jsstr_t *str, jsval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_free(parens);
|
heap_pool_clear(mark);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
#include "jscript.h"
|
#include "jscript.h"
|
||||||
|
#include "regexp.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -626,8 +627,8 @@ static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, jsstr_t *str, match_result_t *match,
|
static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
|
||||||
match_result_t *parens, DWORD parens_cnt, jsstr_t **ret)
|
jsstr_t *str, match_state_t *match, jsstr_t **ret)
|
||||||
{
|
{
|
||||||
jsval_t *argv;
|
jsval_t *argv;
|
||||||
unsigned argc;
|
unsigned argc;
|
||||||
|
@ -636,19 +637,22 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, jsstr_t *str, match_r
|
||||||
DWORD i;
|
DWORD i;
|
||||||
HRESULT hres = S_OK;
|
HRESULT hres = S_OK;
|
||||||
|
|
||||||
argc = parens_cnt+3;
|
argc = match->paren_count+3;
|
||||||
argv = heap_alloc_zero(sizeof(*argv)*argc);
|
argv = heap_alloc_zero(sizeof(*argv)*argc);
|
||||||
if(!argv)
|
if(!argv)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
tmp_str = jsstr_alloc_len(match->str, match->len);
|
tmp_str = jsstr_alloc_len(match->cp-match->match_len, match->match_len);
|
||||||
if(!tmp_str)
|
if(!tmp_str)
|
||||||
hres = E_OUTOFMEMORY;
|
hres = E_OUTOFMEMORY;
|
||||||
argv[0] = jsval_string(tmp_str);
|
argv[0] = jsval_string(tmp_str);
|
||||||
|
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
for(i=0; i < parens_cnt; i++) {
|
for(i=0; i < match->paren_count; i++) {
|
||||||
tmp_str = jsstr_alloc_len(parens[i].str, parens[i].len);
|
if(match->parens[i].index == -1)
|
||||||
|
tmp_str = jsstr_empty();
|
||||||
|
else
|
||||||
|
tmp_str = jsstr_alloc_len(str->str+match->parens[i].index, match->parens[i].length);
|
||||||
if(!tmp_str) {
|
if(!tmp_str) {
|
||||||
hres = E_OUTOFMEMORY;
|
hres = E_OUTOFMEMORY;
|
||||||
break;
|
break;
|
||||||
|
@ -658,14 +662,14 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, jsstr_t *str, match_r
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
argv[parens_cnt+1] = jsval_number(match->str - str->str);
|
argv[match->paren_count+1] = jsval_number(match->cp-str->str - match->match_len);
|
||||||
argv[parens_cnt+2] = jsval_string(str);
|
argv[match->paren_count+2] = jsval_string(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres))
|
||||||
hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, argc, argv, &val);
|
hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, argc, argv, &val);
|
||||||
|
|
||||||
for(i=0; i <= parens_cnt; i++)
|
for(i=0; i <= match->paren_count; i++)
|
||||||
jsstr_release(get_string(argv[i]));
|
jsstr_release(get_string(argv[i]));
|
||||||
heap_free(argv);
|
heap_free(argv);
|
||||||
|
|
||||||
|
@ -681,12 +685,12 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, jsstr_t *str, match_r
|
||||||
static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
DWORD parens_cnt = 0, parens_size=0, rep_len=0;
|
DWORD rep_len=0;
|
||||||
jsstr_t *rep_str = NULL, *match_str = NULL, *str;
|
jsstr_t *rep_str = NULL, *match_str = NULL, *str;
|
||||||
jsdisp_t *rep_func = NULL, *regexp = NULL;
|
jsdisp_t *rep_func = NULL, *regexp = NULL;
|
||||||
match_result_t *parens = NULL, match = {NULL,0}, **parens_ptr = &parens;
|
match_state_t *match = NULL, last_match = {0};
|
||||||
strbuf_t ret = {NULL,0,0};
|
strbuf_t ret = {NULL,0,0};
|
||||||
DWORD re_flags = REM_NO_CTX_UPDATE;
|
DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT;
|
||||||
HRESULT hres = S_OK;
|
HRESULT hres = S_OK;
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
@ -730,24 +734,18 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
|
|
||||||
if(!rep_func) {
|
if(!rep_func) {
|
||||||
hres = to_string(ctx, argv[1], &rep_str);
|
hres = to_string(ctx, argv[1], &rep_str);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres))
|
||||||
rep_len = jsstr_length(rep_str);
|
rep_len = jsstr_length(rep_str);
|
||||||
if(!strchrW(rep_str->str, '$'))
|
|
||||||
parens_ptr = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
const WCHAR *cp, *ecp;
|
const WCHAR *ecp = str->str;
|
||||||
|
|
||||||
cp = ecp = str->str;
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(regexp) {
|
if(regexp) {
|
||||||
hres = regexp_match_next(ctx, regexp, re_flags, str, &cp, parens_ptr,
|
hres = regexp_match_next(ctx, regexp, re_flags, str, &match);
|
||||||
&parens_size, &parens_cnt, &match);
|
re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT);
|
||||||
re_flags |= REM_CHECK_GLOBAL;
|
|
||||||
|
|
||||||
if(hres == S_FALSE) {
|
if(hres == S_FALSE) {
|
||||||
hres = S_OK;
|
hres = S_OK;
|
||||||
|
@ -756,25 +754,31 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(!match.len)
|
last_match.cp = match->cp;
|
||||||
cp++;
|
last_match.match_len = match->match_len;
|
||||||
}else {
|
}else {
|
||||||
match.str = strstrW(cp, match_str->str);
|
if(re_flags & REM_ALLOC_RESULT) {
|
||||||
if(!match.str)
|
re_flags &= ~REM_ALLOC_RESULT;
|
||||||
|
match = &last_match;
|
||||||
|
match->cp = str->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
match->cp = strstrW(match->cp, match_str->str);
|
||||||
|
if(!match->cp)
|
||||||
break;
|
break;
|
||||||
match.len = jsstr_length(match_str);
|
match->match_len = jsstr_length(match_str);
|
||||||
cp = match.str+match.len;
|
match->cp += match->match_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = strbuf_append(&ret, ecp, match.str-ecp);
|
hres = strbuf_append(&ret, ecp, match->cp-ecp-match->match_len);
|
||||||
ecp = match.str+match.len;
|
ecp = match->cp;
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(rep_func) {
|
if(rep_func) {
|
||||||
jsstr_t *cstr;
|
jsstr_t *cstr;
|
||||||
|
|
||||||
hres = rep_call(ctx, rep_func, str, &match, parens, parens_cnt, &cstr);
|
hres = rep_call(ctx, rep_func, str, match, &cstr);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -796,11 +800,11 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
ptr = ptr2+2;
|
ptr = ptr2+2;
|
||||||
break;
|
break;
|
||||||
case '&':
|
case '&':
|
||||||
hres = strbuf_append(&ret, match.str, match.len);
|
hres = strbuf_append(&ret, match->cp-match->match_len, match->match_len);
|
||||||
ptr = ptr2+2;
|
ptr = ptr2+2;
|
||||||
break;
|
break;
|
||||||
case '`':
|
case '`':
|
||||||
hres = strbuf_append(&ret, str->str, match.str-str->str);
|
hres = strbuf_append(&ret, str->str, match->cp-str->str-match->match_len);
|
||||||
ptr = ptr2+2;
|
ptr = ptr2+2;
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
|
@ -817,10 +821,10 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = ptr2[1] - '0';
|
idx = ptr2[1] - '0';
|
||||||
if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= parens_cnt) {
|
if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= match->paren_count) {
|
||||||
idx = idx*10 + (ptr[2]-'0');
|
idx = idx*10 + (ptr[2]-'0');
|
||||||
ptr = ptr2+3;
|
ptr = ptr2+3;
|
||||||
}else if(idx && idx <= parens_cnt) {
|
}else if(idx && idx <= match->paren_count) {
|
||||||
ptr = ptr2+2;
|
ptr = ptr2+2;
|
||||||
}else {
|
}else {
|
||||||
hres = strbuf_append(&ret, ptr2, 1);
|
hres = strbuf_append(&ret, ptr2, 1);
|
||||||
|
@ -828,7 +832,9 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = strbuf_append(&ret, parens[idx-1].str, parens[idx-1].len);
|
if(match->parens[idx-1].index != -1)
|
||||||
|
hres = strbuf_append(&ret, str->str+match->parens[idx-1].index,
|
||||||
|
match->parens[idx-1].length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,6 +860,8 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
|
|
||||||
if(!regexp)
|
if(!regexp)
|
||||||
break;
|
break;
|
||||||
|
else if(!match->match_len)
|
||||||
|
match->cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres))
|
||||||
|
@ -866,13 +874,14 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
|
||||||
jsstr_release(rep_str);
|
jsstr_release(rep_str);
|
||||||
if(match_str)
|
if(match_str)
|
||||||
jsstr_release(match_str);
|
jsstr_release(match_str);
|
||||||
heap_free(parens);
|
if(regexp)
|
||||||
|
heap_free(match);
|
||||||
|
|
||||||
if(SUCCEEDED(hres) && match.str && regexp) {
|
if(SUCCEEDED(hres) && last_match.cp && regexp) {
|
||||||
jsstr_release(ctx->last_match);
|
jsstr_release(ctx->last_match);
|
||||||
ctx->last_match = jsstr_addref(str);
|
ctx->last_match = jsstr_addref(str);
|
||||||
ctx->last_match_index = match.str-str->str;
|
ctx->last_match_index = last_match.cp-str->str-last_match.match_len;
|
||||||
ctx->last_match_length = match.len;
|
ctx->last_match_length = last_match.match_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regexp)
|
if(regexp)
|
||||||
|
@ -898,9 +907,8 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
jsdisp_t *regexp = NULL;
|
jsdisp_t *regexp = NULL;
|
||||||
const WCHAR *cp;
|
|
||||||
match_result_t match;
|
|
||||||
jsstr_t *str;
|
jsstr_t *str;
|
||||||
|
match_state_t match, *match_ptr = &match;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
@ -932,15 +940,15 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = str->str;
|
match.cp = str->str;
|
||||||
hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, &cp, NULL, NULL, NULL, &match);
|
hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, str, &match_ptr);
|
||||||
jsstr_release(str);
|
jsstr_release(str);
|
||||||
jsdisp_release(regexp);
|
jsdisp_release(regexp);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
if(r)
|
if(r)
|
||||||
*r = jsval_number(hres == S_OK ? match.str-str->str : -1);
|
*r = jsval_number(hres == S_OK ? match.cp-match.match_len-str->str : -1);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,9 +1039,9 @@ static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
{
|
{
|
||||||
match_result_t match_result;
|
match_state_t match_result, *match_ptr = &match_result;
|
||||||
DWORD length, i, match_len = 0;
|
DWORD length, i, match_len = 0;
|
||||||
const WCHAR *ptr, *ptr2, *cp;
|
const WCHAR *ptr, *ptr2;
|
||||||
unsigned limit = UINT32_MAX;
|
unsigned limit = UINT32_MAX;
|
||||||
jsdisp_t *array, *regexp = NULL;
|
jsdisp_t *array, *regexp = NULL;
|
||||||
jsstr_t *str, *match_str = NULL, *tmp_str;
|
jsstr_t *str, *match_str = NULL, *tmp_str;
|
||||||
|
@ -1087,13 +1095,14 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
hres = create_array(ctx, 0, &array);
|
hres = create_array(ctx, 0, &array);
|
||||||
|
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
ptr = cp = str->str;
|
ptr = str->str;
|
||||||
|
match_result.cp = str->str;
|
||||||
for(i=0; i<limit; i++) {
|
for(i=0; i<limit; i++) {
|
||||||
if(regexp) {
|
if(regexp) {
|
||||||
hres = regexp_match_next(ctx, regexp, 0, str, &cp, NULL, NULL, NULL, &match_result);
|
hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, str, &match_ptr);
|
||||||
if(hres != S_OK)
|
if(hres != S_OK)
|
||||||
break;
|
break;
|
||||||
ptr2 = match_result.str;
|
ptr2 = match_result.cp - match_result.match_len;
|
||||||
}else if(match_str) {
|
}else if(match_str) {
|
||||||
ptr2 = strstrW(ptr, match_str->str);
|
ptr2 = strstrW(ptr, match_str->str);
|
||||||
if(!ptr2)
|
if(!ptr2)
|
||||||
|
@ -1116,7 +1125,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(regexp)
|
if(regexp)
|
||||||
ptr = cp;
|
ptr = match_result.cp;
|
||||||
else if(match_str)
|
else if(match_str)
|
||||||
ptr = ptr2 + match_len;
|
ptr = ptr2 + match_len;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue