Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
7639a850
Commit
7639a850
authored
Oct 22, 2019
by
Jacek Caban
Committed by
Alexandre Julliard
Oct 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vbscript: Implement RegExp.Replace.
Signed-off-by:
Jacek Caban
<
jacek@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
ea5dbc13
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
6 deletions
+206
-6
regexp.vbs
dlls/vbscript/tests/regexp.vbs
+34
-1
vbregexp.c
dlls/vbscript/vbregexp.c
+172
-5
No files found.
dlls/vbscript/tests/regexp.vbs
View file @
7639a850
...
...
@@ -18,7 +18,7 @@
Option
Explicit
Dim
x
,
matches
,
match
,
submatch
Dim
x
,
matches
,
match
,
submatch
,
r
Set
x
=
CreateObject
(
"vbscript.regexp"
)
Call
ok
(
getVT
(
x
.
Pattern
)
=
"VT_BSTR"
,
"getVT(RegExp.Pattern) = "
&
getVT
(
x
.
Pattern
))
...
...
@@ -191,4 +191,37 @@ Call ok(match.Value = "", "match.Value = " & match.Value)
matches
=
x
.
test
(
"test"
)
Call
ok
(
matches
=
true
,
"matches = "
&
matches
)
dim
test_global
sub
test_replace
(
pattern
,
string
,
rep
,
exp
)
dim
x
,
re
set
re
=
new
regexp
re
.
pattern
=
pattern
re
.
global
=
test_global
x
=
re
.
replace
(
string
,
rep
)
call
ok
(
x
=
exp
,
"replace returned "
&
x
&
" expected "
&
exp
)
end
sub
test_global
=
true
test_replace
"xxx"
,
"xxxx"
,
"y"
,
"yx"
test_replace
"\[([^\[]+)\]"
,
"- [test] -"
,
"success"
,
"- success -"
test_replace
"\[([^\[]+)\]"
,
"[test] [test]"
,
"aa"
,
"aa aa"
test_replace
"(\&(\d))"
,
"abc &1 123"
,
"$'"
,
"abc 123 123"
test_replace
"(\&(\d))"
,
"abc &1 123"
,
"$`"
,
"abc abc 123"
test_replace
"(\&(\d))"
,
"abc &1 123"
,
"$3"
,
"abc $3 123"
test_replace
"\[([^\[]+)\]"
,
"- [test] -"
,
true
,
"- -1 -"
test_replace
"\[([^\[]+)\]"
,
"- [test] -"
,
6
,
"- 6 -"
test_replace
"(\$(\d))"
,
"$1,$2"
,
"$$1-$1$2"
,
"$1-$11,$1-$22"
test_replace
"b"
,
"abc"
,
"x$&z"
,
"axbzc"
test_global
=
false
test_replace
"\[([^\[]+)\]"
,
"[test] [test]"
,
"aa"
,
"aa [test]"
set
r
=
new
regexp
x
=
r
.
replace
(
"xxx"
,
"y"
)
call
ok
(
x
=
"yxxx"
,
"x = "
&
x
)
r
.
global
=
true
x
=
r
.
replace
(
"xxx"
,
"y"
)
call
ok
(
x
=
"yxyxyxy"
,
"x = "
&
x
)
Call
reportSuccess
()
dlls/vbscript/vbregexp.c
View file @
7639a850
...
...
@@ -19,6 +19,7 @@
#include "vbscript.h"
#include "regexp.h"
#include "vbsregexp55.h"
#include "wchar.h"
#include "wine/debug.h"
...
...
@@ -1432,13 +1433,179 @@ static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_B
return
hres
;
}
static
HRESULT
WINAPI
RegExp2_Replace
(
IRegExp2
*
iface
,
BSTR
sourceString
,
VARIANT
replaceVar
,
BSTR
*
pDestString
)
typedef
struct
{
WCHAR
*
buf
;
DWORD
size
;
DWORD
len
;
}
strbuf_t
;
static
BOOL
strbuf_ensure_size
(
strbuf_t
*
buf
,
unsigned
len
)
{
WCHAR
*
new_buf
;
DWORD
new_size
;
if
(
len
<=
buf
->
size
)
return
TRUE
;
new_size
=
buf
->
size
?
buf
->
size
<<
1
:
16
;
if
(
new_size
<
len
)
new_size
=
len
;
if
(
buf
->
buf
)
new_buf
=
heap_realloc
(
buf
->
buf
,
new_size
*
sizeof
(
WCHAR
));
else
new_buf
=
heap_alloc
(
new_size
*
sizeof
(
WCHAR
));
if
(
!
new_buf
)
return
FALSE
;
buf
->
buf
=
new_buf
;
buf
->
size
=
new_size
;
return
TRUE
;
}
static
HRESULT
strbuf_append
(
strbuf_t
*
buf
,
const
WCHAR
*
str
,
DWORD
len
)
{
if
(
!
len
)
return
S_OK
;
if
(
!
strbuf_ensure_size
(
buf
,
buf
->
len
+
len
))
return
E_OUTOFMEMORY
;
memcpy
(
buf
->
buf
+
buf
->
len
,
str
,
len
*
sizeof
(
WCHAR
));
buf
->
len
+=
len
;
return
S_OK
;
}
static
HRESULT
WINAPI
RegExp2_Replace
(
IRegExp2
*
iface
,
BSTR
source
,
VARIANT
replaceVar
,
BSTR
*
ret
)
{
RegExp2
*
This
=
impl_from_IRegExp2
(
iface
);
FIXME
(
"(%p)->(%s %s %p)
\n
"
,
This
,
debugstr_w
(
sourceString
),
debugstr_variant
(
&
replaceVar
),
pDestString
);
return
E_NOTIMPL
;
const
WCHAR
*
cp
,
*
prev_cp
=
NULL
,
*
ptr
,
*
prev_ptr
;
size_t
match_len
=
0
,
source_len
,
replace_len
;
strbuf_t
buf
=
{
NULL
,
0
,
0
};
match_state_t
*
state
=
NULL
;
heap_pool_t
*
mark
;
VARIANT
strv
;
BSTR
replace
;
HRESULT
hres
;
TRACE
(
"(%p)->(%s %s %p)
\n
"
,
This
,
debugstr_w
(
source
),
debugstr_variant
(
&
replaceVar
),
ret
);
if
(
This
->
pattern
)
{
if
(
!
This
->
regexp
)
{
This
->
regexp
=
regexp_new
(
NULL
,
&
This
->
pool
,
This
->
pattern
,
lstrlenW
(
This
->
pattern
),
This
->
flags
,
FALSE
);
if
(
!
This
->
regexp
)
return
E_OUTOFMEMORY
;
}
else
{
hres
=
regexp_set_flags
(
&
This
->
regexp
,
NULL
,
&
This
->
pool
,
This
->
flags
);
if
(
FAILED
(
hres
))
return
hres
;
}
}
V_VT
(
&
strv
)
=
VT_EMPTY
;
hres
=
VariantChangeType
(
&
strv
,
&
replaceVar
,
0
,
VT_BSTR
);
if
(
FAILED
(
hres
))
return
hres
;
replace
=
V_BSTR
(
&
strv
);
replace_len
=
SysStringLen
(
replace
);
source_len
=
SysStringLen
(
source
);
mark
=
heap_pool_mark
(
&
This
->
pool
);
cp
=
source
;
if
(
This
->
regexp
&&
!
(
state
=
alloc_match_state
(
This
->
regexp
,
&
This
->
pool
,
cp
)))
hres
=
E_OUTOFMEMORY
;
while
(
SUCCEEDED
(
hres
))
{
if
(
This
->
regexp
)
{
prev_cp
=
cp
;
hres
=
regexp_execute
(
This
->
regexp
,
NULL
,
&
This
->
pool
,
source
,
source_len
,
state
);
if
(
hres
!=
S_OK
)
break
;
cp
=
state
->
cp
;
match_len
=
state
->
match_len
;
}
else
if
(
prev_cp
)
{
if
(
cp
==
source
+
source_len
)
break
;
prev_cp
=
cp
++
;
}
else
{
prev_cp
=
cp
;
}
hres
=
strbuf_append
(
&
buf
,
prev_cp
,
cp
-
prev_cp
-
match_len
);
if
(
FAILED
(
hres
))
break
;
prev_ptr
=
replace
;
while
((
ptr
=
wmemchr
(
prev_ptr
,
'$'
,
replace
+
replace_len
-
prev_ptr
)))
{
hres
=
strbuf_append
(
&
buf
,
prev_ptr
,
ptr
-
prev_ptr
);
if
(
FAILED
(
hres
))
break
;
switch
(
ptr
[
1
])
{
case
'$'
:
hres
=
strbuf_append
(
&
buf
,
ptr
,
1
);
prev_ptr
=
ptr
+
2
;
break
;
case
'&'
:
hres
=
strbuf_append
(
&
buf
,
cp
-
match_len
,
match_len
);
prev_ptr
=
ptr
+
2
;
break
;
case
'`'
:
hres
=
strbuf_append
(
&
buf
,
source
,
cp
-
source
-
match_len
);
prev_ptr
=
ptr
+
2
;
break
;
case
'\''
:
hres
=
strbuf_append
(
&
buf
,
cp
,
source
+
source_len
-
cp
);
prev_ptr
=
ptr
+
2
;
break
;
default:
{
DWORD
idx
;
if
(
!
iswdigit
(
ptr
[
1
]))
{
hres
=
strbuf_append
(
&
buf
,
ptr
,
1
);
prev_ptr
=
ptr
+
1
;
break
;
}
idx
=
ptr
[
1
]
-
'0'
;
if
(
iswdigit
(
ptr
[
2
])
&&
idx
*
10
+
(
ptr
[
2
]
-
'0'
)
<=
state
->
paren_count
)
{
idx
=
idx
*
10
+
(
ptr
[
2
]
-
'0'
);
prev_ptr
=
ptr
+
3
;
}
else
if
(
idx
&&
idx
<=
state
->
paren_count
)
{
prev_ptr
=
ptr
+
2
;
}
else
{
hres
=
strbuf_append
(
&
buf
,
ptr
,
1
);
prev_ptr
=
ptr
+
1
;
break
;
}
if
(
state
->
parens
[
idx
-
1
].
index
!=
-
1
)
hres
=
strbuf_append
(
&
buf
,
source
+
state
->
parens
[
idx
-
1
].
index
,
state
->
parens
[
idx
-
1
].
length
);
break
;
}
}
if
(
FAILED
(
hres
))
break
;
}
if
(
SUCCEEDED
(
hres
))
hres
=
strbuf_append
(
&
buf
,
prev_ptr
,
replace
+
replace_len
-
prev_ptr
);
if
(
FAILED
(
hres
))
break
;
if
(
!
(
This
->
flags
&
REG_GLOB
))
break
;
}
if
(
SUCCEEDED
(
hres
))
{
hres
=
strbuf_append
(
&
buf
,
cp
,
source
+
source_len
-
cp
);
if
(
SUCCEEDED
(
hres
)
&&
!
(
*
ret
=
SysAllocStringLen
(
buf
.
buf
,
buf
.
len
)))
hres
=
E_OUTOFMEMORY
;
}
heap_pool_clear
(
mark
);
heap_free
(
buf
.
buf
);
SysFreeString
(
replace
);
return
hres
;
}
static
const
IRegExp2Vtbl
RegExp2Vtbl
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment