Commit 143a072b authored by Geoff Simmons's avatar Geoff Simmons

add the suball() method and function

parent 24e18af8
......@@ -35,11 +35,13 @@ CONTENTS
* BOOL regex.match(STRING)
* STRING regex.namedref(STRING, STRING)
* STRING regex.sub(STRING, STRING, STRING)
* STRING regex.suball(STRING, STRING, STRING)
* Object set
* VOID set.add(STRING)
* VOID set.compile()
* BOOL set.match(STRING)
* STRING sub(STRING, STRING, STRING, STRING, BOOL, BOOL, BOOL, INT, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL)
* STRING suball(STRING, STRING, STRING, STRING, BOOL, BOOL, BOOL, INT, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL)
* STRING version()
.. _obj_regex:
......@@ -80,6 +82,14 @@ STRING regex.sub(STRING, STRING, STRING)
Prototype
STRING regex.sub(STRING text, STRING rewrite, STRING fallback)
.. _func_regex.suball:
STRING regex.suball(STRING, STRING, STRING)
-------------------------------------------
Prototype
STRING regex.suball(STRING text, STRING rewrite, STRING fallback)
.. _obj_set:
Object set
......@@ -142,6 +152,14 @@ STRING sub(STRING, STRING, STRING, STRING, BOOL, BOOL, BOOL, INT, BOOL, BOOL, BO
Prototype
STRING sub(STRING pattern, STRING text, STRING rewrite, STRING fallback, BOOL utf8, BOOL posix_syntax, BOOL longest_match, INT max_mem, BOOL literal, BOOL never_nl, BOOL dot_nl, BOOL never_capture, BOOL case_sensitive, BOOL perl_classes, BOOL word_boundary, BOOL one_line)
.. _func_suball:
STRING suball(STRING, STRING, STRING, STRING, BOOL, BOOL, BOOL, INT, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL)
--------------------------------------------------------------------------------------------------------------------
Prototype
STRING suball(STRING pattern, STRING text, STRING rewrite, STRING fallback, BOOL utf8, BOOL posix_syntax, BOOL longest_match, INT max_mem, BOOL literal, BOOL never_nl, BOOL dot_nl, BOOL never_capture, BOOL case_sensitive, BOOL perl_classes, BOOL word_boundary, BOOL one_line)
.. _func_version:
STRING version()
......
# looks like -*- vcl -*-
varnishtest "suball() method and function"
varnish v1 -vcl {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
backend be { .host = "${bad_ip}"; }
sub vcl_init {
new piglatin = re2.regex("(qu|[b-df-hj-np-tv-z]*)([a-z]+)");
new word = re2.regex("\w+");
new start = re2.regex("^");
new end = re2.regex("$");
new b = re2.regex("b");
new bplus = re2.regex("b+");
new bstar = re2.regex("b*");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
# Tests from re2 testing/re2_test.cc
set resp.http.pangram =
piglatin.suball("the quick brown fox jumps over the lazy dogs.",
"\2\1ay");
set resp.http.nospam = word.suball("abcd.efghi@google.com",
"\0-NOSPAM");
set resp.http.startfoo = start.suball("foo", "(START)");
set resp.http.start = start.suball("", "(START)");
set resp.http.end = end.suball("", "(END)");
set resp.http.ab = b.suball("ababababab", "bb");
set resp.http.bb = b.suball("bbbbbb", "bb");
set resp.http.bplus = bplus.suball("bbbbbb", "bb");
set resp.http.bstar1 = bstar.suball("bbbbbb", "bb");
set resp.http.bstar2 = bstar.suball("aaaaa", "bb");
set resp.http.pangramf
= re2.suball("(qu|[b-df-hj-np-tv-z]*)([a-z]+)",
"the quick brown fox jumps over the lazy dogs.",
"\2\1ay");
set resp.http.nospamf = re2.suball("\w+",
"abcd.efghi@google.com",
"\0-NOSPAM");
set resp.http.startfoof = re2.suball("^", "foo", "(START)");
set resp.http.startf = re2.suball("^", "", "(START)");
set resp.http.endf = re2.suball("$", "", "(END)");
set resp.http.abf = re2.suball("b", "ababababab", "bb");
set resp.http.bbf = re2.suball("b", "bbbbbb", "bb");
set resp.http.bplusf = re2.suball("b+", "bbbbbb", "bb");
set resp.http.bstar1f = re2.suball("b*", "bbbbbb", "bb");
set resp.http.bstar2f = re2.suball("b*", "aaaaa", "bb");
# Match failure
set resp.http.bfail = b.suball("acd", "x", "fallbackb");
set resp.http.bfailf = re2.suball("b", "acd", "x", "fallbackf");
# Undefined fallback
set resp.http.undeffallback
= b.suball("b", "x", req.http.undef);
set resp.http.undeffallbackf
= re2.suball("b", "b", "x", req.http.undef);
# Undefined pattern in the function
set resp.http.undefpattern
= re2.suball(req.http.undef, "", "", "pattern undef");
# Undefined text
set resp.http.undeftext
= b.suball(req.http.undef, "x", "text undef");
set resp.http.undeftextf
= re2.suball("b", req.http.undef, "x", "text undef");
# Undefined rewrite
set resp.http.undefrewrite
= b.suball("b", req.http.undef, "rewrite undef");
set resp.http.undefrewritef
= re2.suball("b", "b", req.http.undef, "rewrite undef");
}
} -start
client c1 {
txreq
rxresp
expect resp.http.pangram == "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday."
expect resp.http.nospam == "abcd-NOSPAM.efghi-NOSPAM@google-NOSPAM.com-NOSPAM"
expect resp.http.startfoo == "(START)foo"
expect resp.http.start == "(START)"
expect resp.http.end == "(END)"
expect resp.http.ab == "abbabbabbabbabb"
expect resp.http.bb == "bbbbbbbbbbbb"
expect resp.http.bplus == "bb"
expect resp.http.bstar1 == "bb"
expect resp.http.bstar2 == "bbabbabbabbabbabb"
expect resp.http.pangramf == "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday."
expect resp.http.nospamf == "abcd-NOSPAM.efghi-NOSPAM@google-NOSPAM.com-NOSPAM"
expect resp.http.startfoof == "(START)foo"
expect resp.http.startf == "(START)"
expect resp.http.endf == "(END)"
expect resp.http.abf == "abbabbabbabbabb"
expect resp.http.bbf == "bbbbbbbbbbbb"
expect resp.http.bplusf == "bb"
expect resp.http.bstar1f == "bb"
expect resp.http.bstar2f == "bbabbabbabbabbabb"
expect resp.http.bfail == "fallbackb"
expect resp.http.bfailf == "fallbackf"
expect resp.http.undeffallback == "**SUBALL METHOD FAILED**"
expect resp.http.undeffallbackf == "**SUBALL FUNCTION FAILED**"
expect resp.http.undefpattern == "pattern undef"
expect resp.http.undeftext == "text undef"
expect resp.http.undeftextf == "text undef"
expect resp.http.undefrewrite == "rewrite undef"
expect resp.http.undefrewritef == "rewrite undef"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: b.suball..: fallback is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.suball..: fallback is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.suball.pattern=<undefined>, fallback=.pattern undef..: pattern is undefined$"
expect * = VCL_Error "^vmod re2 error: b.suball.text=<undefined>, fallback=.text undef..: text is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.suball.pattern=.b., text=<undefined>, fallback=.text undef..: text is undefined$"
expect * = VCL_Error "^vmod re2 error: b.suball.text=.b., rewrite=<undefined>, fallback=.rewrite undef..: rewrite is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.suball.pattern=.b., text=.b., rewrite=<undefined>, fallback=.rewrite undef..: rewrite is undefined$"
expect * = End
} -run
......@@ -238,8 +238,8 @@ namedref(VRT_CTX, vre2 * restrict vre2, VCL_STRING name, VCL_STRING fallback,
#define ERR_PREFIX "sub(text=\"%s\", rewrite=\"%s\", fallback=\"%s\"): "
static VCL_STRING
sub(VRT_CTX, vre2 * restrict vre2, VCL_STRING text, VCL_STRING rewrite,
VCL_STRING fallback)
sub(VRT_CTX, vre2 * restrict vre2, const int all, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
{
int match = 0;
size_t bytes, len;
......@@ -248,7 +248,8 @@ sub(VRT_CTX, vre2 * restrict vre2, VCL_STRING text, VCL_STRING rewrite,
ret = WS_Snapshot(ctx->ws);
bytes = WS_Reserve(ctx->ws, 0);
if ((err = vre2_replace(vre2, text, rewrite, ret, bytes, &match, &len))
if ((err = vre2_replace(vre2, all, text, rewrite, ret, bytes, &match,
&len))
!= NULL) {
VERR(ctx, ERR_PREFIX "%s", text, rewrite, fallback, err);
WS_Release(ctx->ws, 0);
......@@ -418,29 +419,48 @@ vmod_regex_namedref(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING name,
#undef ERR_PREFIX
VCL_STRING
vmod_regex_sub(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
static VCL_STRING
sub_method(VRT_CTX, const char * const restrict mname, const int all,
struct vmod_re2_regex * restrict re, VCL_STRING restrict text,
VCL_STRING restrict rewrite, VCL_STRING restrict fallback)
{
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(re, VMOD_RE2_REGEX_MAGIC);
if (fallback == NULL) {
VERR(ctx, "%s.sub(): fallback is undefined", re->vcl_name);
return "**SUB METHOD FAILED**";
VERR(ctx, "%s.%s(): fallback is undefined", re->vcl_name,
mname);
if (all)
return "**SUBALL METHOD FAILED**";
else
return "**SUB METHOD FAILED**";
}
if (text == NULL) {
VERR(ctx, "%s.sub(text=<undefined>, fallback=\"%s\"): "
"text is undefined", re->vcl_name, fallback);
VERR(ctx, "%s.%s(text=<undefined>, fallback=\"%s\"): "
"text is undefined", re->vcl_name, mname, fallback);
return fallback;
}
if (rewrite == NULL) {
VERR(ctx, "%s.sub(text=\"%s\", rewrite=<undefined>, "
VERR(ctx, "%s.%s(text=\"%s\", rewrite=<undefined>, "
"fallback=\"%s\"): rewrite is undefined", re->vcl_name,
text, fallback);
mname, text, fallback);
return fallback;
}
return sub(ctx, re->vre2, text, rewrite, fallback);
return sub(ctx, re->vre2, all, text, rewrite, fallback);
}
VCL_STRING
vmod_regex_sub(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
{
return sub_method(ctx, "sub", 0, re, text, rewrite, fallback);
}
VCL_STRING
vmod_regex_suball(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
{
return sub_method(ctx, "suball", 1, re, text, rewrite, fallback);
}
/* Object set */
......@@ -727,38 +747,43 @@ vmod_namedref(VRT_CTX, struct vmod_priv *priv, VCL_STRING name,
#undef ERR_PREFIX
#define ERR_PREFIX "re2.sub(pattern=\"%s\", text=\"%s\", rewrite=\"%s\", fallback=\"%s\"): "
#define ERR_PREFIX "re2.%s(pattern=\"%s\", text=\"%s\", rewrite=\"%s\", fallback=\"%s\"): "
VCL_STRING
vmod_sub(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
VCL_STRING fallback, VCL_BOOL utf8, VCL_BOOL posix_syntax,
VCL_BOOL longest_match, VCL_INT max_mem, VCL_BOOL literal,
VCL_BOOL never_nl, VCL_BOOL dot_nl, VCL_BOOL never_capture,
VCL_BOOL case_sensitive, VCL_BOOL perl_classes, VCL_BOOL word_boundary,
VCL_BOOL one_line)
static VCL_STRING
sub_function(VRT_CTX, const char * const restrict fname, const int all,
VCL_STRING restrict pattern, VCL_STRING restrict text,
VCL_STRING restrict rewrite, VCL_STRING restrict fallback,
VCL_BOOL utf8, VCL_BOOL posix_syntax, VCL_BOOL longest_match,
VCL_INT max_mem, VCL_BOOL literal, VCL_BOOL never_nl,
VCL_BOOL dot_nl, VCL_BOOL never_capture, VCL_BOOL case_sensitive,
VCL_BOOL perl_classes, VCL_BOOL word_boundary, VCL_BOOL one_line)
{
vre2 *vre2 = NULL;
const char *ret, *err;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (fallback == NULL) {
ERR(ctx, "re2.sub(): fallback is undefined");
return "**SUB FUNCTION FAILED**";
VERR(ctx, "re2.%s(): fallback is undefined", fname);
if (all)
return "**SUBALL FUNCTION FAILED**";
else
return "**SUB FUNCTION FAILED**";
}
if (pattern == NULL) {
VERR(ctx, "re2.sub(pattern=<undefined>, fallback=\"%s\"): "
"pattern is undefined", fallback);
VERR(ctx, "re2.%s(pattern=<undefined>, fallback=\"%s\"): "
"pattern is undefined", fname, fallback);
return fallback;
}
if (text == NULL) {
VERR(ctx, "re2.sub(pattern=\"%s\", text=<undefined>, "
"fallback=\"%s\"): text is undefined", pattern, fallback);
VERR(ctx, "re2.%s(pattern=\"%s\", text=<undefined>, "
"fallback=\"%s\"): text is undefined", fname, pattern,
fallback);
return fallback;
}
if (rewrite == NULL) {
VERR(ctx, "re2.sub(pattern=\"%s\", text=\"%s\", "
VERR(ctx, "re2.%s(pattern=\"%s\", text=\"%s\", "
"rewrite=<undefined>, fallback=\"%s\"): "
"rewrite is undefined", pattern, text, fallback);
"rewrite is undefined", fname, pattern, text, fallback);
return fallback;
}
......@@ -767,18 +792,46 @@ vmod_sub(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
case_sensitive, perl_classes, word_boundary,
one_line))
!= NULL) {
VERR(ctx, ERR_PREFIX "Cannot compile '%s': %s", pattern, text,
rewrite, fallback, pattern, err);
VERR(ctx, ERR_PREFIX "Cannot compile '%s': %s", fname, pattern,
text, rewrite, fallback, pattern, err);
vre2_fini(&vre2);
return fallback;
}
ret = sub(ctx, vre2, text, rewrite, fallback);
ret = sub(ctx, vre2, all, text, rewrite, fallback);
vre2_fini(&vre2);
return ret;
}
#undef ERR_PREFIX
VCL_STRING
vmod_sub(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
VCL_STRING fallback, VCL_BOOL utf8, VCL_BOOL posix_syntax,
VCL_BOOL longest_match, VCL_INT max_mem, VCL_BOOL literal,
VCL_BOOL never_nl, VCL_BOOL dot_nl, VCL_BOOL never_capture,
VCL_BOOL case_sensitive, VCL_BOOL perl_classes, VCL_BOOL word_boundary,
VCL_BOOL one_line)
{
return sub_function(ctx, "sub", 0, pattern, text, rewrite, fallback,
utf8, posix_syntax, longest_match, max_mem, literal,
never_nl, dot_nl, never_capture, case_sensitive,
perl_classes, word_boundary, one_line);
}
VCL_STRING
vmod_suball(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
VCL_STRING fallback, VCL_BOOL utf8, VCL_BOOL posix_syntax,
VCL_BOOL longest_match, VCL_INT max_mem, VCL_BOOL literal,
VCL_BOOL never_nl, VCL_BOOL dot_nl, VCL_BOOL never_capture,
VCL_BOOL case_sensitive, VCL_BOOL perl_classes, VCL_BOOL word_boundary,
VCL_BOOL one_line)
{
return sub_function(ctx, "suball", 1, pattern, text, rewrite, fallback,
utf8, posix_syntax, longest_match, max_mem, literal,
never_nl, dot_nl, never_capture, case_sensitive,
perl_classes, word_boundary, one_line);
}
VCL_STRING
vmod_version(const struct vrt_ctx *ctx __attribute__((unused)))
{
......
......@@ -27,6 +27,9 @@ $Method STRING .namedref(STRING name,
$Method STRING .sub(STRING text, STRING rewrite,
STRING fallback = "**SUB METHOD FAILED**")
$Method STRING .suball(STRING text, STRING rewrite,
STRING fallback = "**SUBALL METHOD FAILED**")
$Object set(ENUM { none, start, both } anchor="none", BOOL utf8=0,
BOOL posix_syntax=0, BOOL longest_match=0, INT max_mem=8388608,
BOOL literal=0, BOOL never_nl=0, BOOL dot_nl=0,
......@@ -59,4 +62,12 @@ $Function STRING sub(STRING pattern, STRING text, STRING rewrite,
BOOL dot_nl=0, BOOL never_capture=0, BOOL case_sensitive=1,
BOOL perl_classes=0, BOOL word_boundary=0, BOOL one_line=0)
$Function STRING suball(STRING pattern, STRING text, STRING rewrite,
STRING fallback = "**SUB FUNCTION FAILED**",
BOOL utf8=0, BOOL posix_syntax=0, BOOL longest_match=0,
INT max_mem=8388608, BOOL literal=0, BOOL never_nl=0,
BOOL dot_nl=0, BOOL never_capture=0,
BOOL case_sensitive=1, BOOL perl_classes=0,
BOOL word_boundary=0, BOOL one_line=0)
$Function STRING version()
......@@ -86,6 +86,12 @@ vre2::replace(string *text, const char * const rewrite) const
return RE2::Replace(text, *re_, rewrite);
}
inline bool
vre2::global_replace(string *text, const char * const rewrite) const
{
return RE2::GlobalReplace(text, *re_, rewrite);
}
const char *
vre2_init(vre2 **vre2p, const char *pattern, unsigned utf8,
unsigned posix_syntax, unsigned longest_match, long max_mem,
......@@ -170,13 +176,16 @@ vre2_get_group(vre2 *vre2, const char * const name, int * const refnum)
}
const char *
vre2_replace(vre2 *vre2, const char * const text, const char * const rewrite,
char * const dest, const size_t bytes, int * const match,
size_t * const len)
vre2_replace(vre2 *vre2, const int all, const char * const text,
const char * const rewrite, char * const dest, const size_t bytes,
int * const match, size_t * const len)
{
try {
string t(text);
*match = vre2->replace(&t, rewrite);
if (all)
*match = vre2->global_replace(&t, rewrite);
else
*match = vre2->replace(&t, rewrite);
if (!*match)
return NULL;
if (t.size() + 1 > bytes)
......
......@@ -49,6 +49,7 @@ public:
const int ngroups() const;
int get_group(const char * const name) const;
bool replace(string *text, const char * const rewrite) const;
bool global_replace(string *text, const char * const rewrite) const;
};
#else
typedef struct vre2 vre2;
......@@ -75,7 +76,8 @@ extern "C" {
const char ** const capture, int * const len);
const char *vre2_get_group(vre2 *vre2, const char * const name,
int * const refnum);
const char *vre2_replace(vre2 *vre2, const char * const text,
const char *vre2_replace(vre2 *vre2, const int all,
const char * const text,
const char * const rewrite,
char * const dest, const size_t bytes,
int * const match, size_t * const len);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment