Commit 2101e6d4 authored by Geoff Simmons's avatar Geoff Simmons

add the regex.sub() method

parent 2f698cdf
......@@ -34,6 +34,7 @@ CONTENTS
* STRING regex.backref(INT, STRING)
* BOOL regex.match(STRING)
* STRING regex.namedref(STRING, STRING)
* STRING regex.sub(STRING, STRING, STRING)
* Object set
* VOID set.add(STRING)
* VOID set.compile()
......@@ -70,6 +71,14 @@ STRING regex.namedref(STRING, STRING)
Prototype
STRING regex.namedref(STRING name, STRING fallback)
.. _func_regex.sub:
STRING regex.sub(STRING, STRING, STRING)
----------------------------------------
Prototype
STRING regex.sub(STRING text, STRING rewrite, STRING fallback)
.. _obj_set:
Object set
......
# looks like -*- vcl -*-
varnishtest "sub() method"
# Tests from re2 testing/re2_test.cc
# regex object
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 {
set resp.http.pangram
= piglatin.sub("the quick brown fox jumps over the lazy dogs.",
"\2\1ay");
set resp.http.nospam = word.sub("abcd.efghi@google.com",
"\0-NOSPAM");
set resp.http.startfoo = start.sub("foo", "(START)");
set resp.http.start = start.sub("", "(START)");
set resp.http.end = end.sub("", "(END)");
set resp.http.ab = b.sub("ababababab", "bb");
set resp.http.bb = b.sub("bbbbbb", "bb");
set resp.http.bplus = bplus.sub("bbbbbb", "bb");
set resp.http.bstar1 = bstar.sub("bbbbbb", "bb");
set resp.http.bstar2 = bstar.sub("aaaaa", "bb");
}
} -start
client c1 {
txreq
rxresp
expect resp.http.pangram == "ethay quick brown fox jumps over the lazy dogs."
expect resp.http.nospam == "abcd-NOSPAM.efghi@google.com"
expect resp.http.startfoo == "(START)foo"
expect resp.http.start == "(START)"
expect resp.http.end == "(END)"
expect resp.http.ab == "abbabababab"
expect resp.http.bb == "bbbbbbb"
expect resp.http.bplus == "bb"
expect resp.http.bstar1 == "bb"
expect resp.http.bstar2 == "bbaaaaa"
} -run
......@@ -381,6 +381,45 @@ vmod_regex_namedref(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING name,
#undef ERR_PREFIX
#define ERR_PREFIX "%s.sub(text=\"%s\", rewrite=\"%s\", fallback=\"%s\"): "
VCL_STRING
vmod_regex_sub(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
{
int match = 0;
size_t bytes, len;
char *ret;
const char *err;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(re, VMOD_RE2_REGEX_MAGIC);
if (text == NULL)
text = "";
if (rewrite == NULL)
rewrite = "";
if (fallback == NULL)
fallback = "";
ret = WS_Snapshot(ctx->ws);
bytes = WS_Reserve(ctx->ws, 0);
if ((err = vre2_replace(re->vre2, text, rewrite, ret, bytes, &match,
&len)) != NULL) {
VERR(ctx, ERR_PREFIX "%s", re->vcl_name, text, rewrite,
fallback, err);
WS_Release(ctx->ws, 0);
return fallback;
}
if (!match) {
WS_Release(ctx->ws, 0);
return fallback;
}
WS_Release(ctx->ws, len);
return ret;
}
#undef ERR_PREFIX
/* Object set */
VCL_VOID
......
......@@ -24,6 +24,9 @@ $Method STRING .backref(INT ref, STRING fallback = "**BACKREF METHOD FAILED**")
$Method STRING .namedref(STRING name,
STRING fallback = "**NAMEDREF METHOD FAILED**")
$Method STRING .sub(STRING text, STRING rewrite,
STRING fallback = "**SUB 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,
......
......@@ -81,6 +81,12 @@ vre2::get_group(const char * const name) const
}
}
inline bool
vre2::replace(string *text, const char * const rewrite) const
{
return RE2::Replace(text, *re_, rewrite);
}
const char *
vre2_init(vre2 **vre2p, const char *pattern, unsigned utf8,
unsigned posix_syntax, unsigned longest_match, long max_mem,
......@@ -164,6 +170,26 @@ vre2_get_group(vre2 *vre2, const char * const name, int * const refnum)
CATCHALL
}
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)
{
try {
string t(text);
*match = vre2->replace(&t, rewrite);
if (!*match)
return NULL;
if (t.size() > bytes + 1)
throw runtime_error("insufficient workspace");
*len = t.size() + 1;
t.copy(dest, *len);
dest[*len] = '\0';
return NULL;
}
CATCHALL
}
const char *
vre2_fini(vre2 **vre2)
{
......
......@@ -48,6 +48,7 @@ public:
StringPiece* groups) const;
const int ngroups() const;
int get_group(const char * const name) const;
bool replace(string *text, const char * const rewrite) const;
};
#else
typedef struct vre2 vre2;
......@@ -74,6 +75,10 @@ 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 * const rewrite,
char * const dest, const size_t bytes,
int * const match, size_t * const len);
#ifdef __cplusplus
}
......
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