Commit 09ccf296 authored by Geoff Simmons's avatar Geoff Simmons

Add the .backref() method.

parent 38f73570
......@@ -63,6 +63,15 @@ regex.match
BOOL regex.match(PRIV_CALL, PRIV_TASK, STRING subject, INT len=0, BOOL anchored=0, INT match_limit=0, INT offset_limit=0, BOOL notbol=0, BOOL noteol=0, BOOL notempty=0, BOOL notempty_atstart=0, BOOL no_jit=0, BOOL no_utf_check=0, ENUM {HARD,SOFT} partial=0, INT recursion_limit=0)
.. _func_regex.backref:
regex.backref
-------------
::
STRING regex.backref(INT ref, STRING fallback="**BACKREF METHOD FAILED**")
.. _func_config_bool:
config_bool
......
# looks like -*- vcl -*-
varnishtest "basic backrefs"
varnish v1 -vcl {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new barbaz = pcre2.regex("(bar)(baz)");
new bazplus = pcre2.regex("(baz)(.+)");
new fourdots = pcre2.regex("(.)(.)(.)(.)");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
# Tests task scopes for two different objects
if (barbaz.match("barbaz") && bazplus.match("bazquux")) {
set resp.http.bar0 = barbaz.backref(0, "error0");
set resp.http.bar1 = barbaz.backref(1, "error1");
set resp.http.bar2 = barbaz.backref(2, "error2");
set resp.http.baz0 = bazplus.backref(0, "error0");
set resp.http.baz1 = bazplus.backref(1, "error1");
set resp.http.baz2 = bazplus.backref(2, "error2");
}
else {
set resp.status = 999;
}
if (fourdots.match("barf")) {
set resp.http.frap
= "_" + fourdots.backref(0, "error0") + "_"
+ fourdots.backref(4, "error4")
+ fourdots.backref(3, "error3")
+ fourdots.backref(2, "error2") + "p_";
}
else {
set resp.status = 999;
}
}
} -start
client c1 -repeat 2 {
txreq
rxresp
expect resp.status == "200"
expect resp.http.bar0 == "barbaz"
expect resp.http.bar1 == "bar"
expect resp.http.bar2 == "baz"
expect resp.http.baz0 == "bazquux"
expect resp.http.baz1 == "baz"
expect resp.http.baz2 == "quux"
expect resp.http.frap == "_barf_frap_"
} -run
......@@ -519,6 +519,46 @@ vmod_regex_match(VRT_CTX, struct vmod_pcre2_regex *regex,
return 0;
}
VCL_STRING
vmod_regex_backref(VRT_CTX, struct vmod_pcre2_regex *regex, VCL_INT ref,
VCL_STRING fallback)
{
struct vmod_priv *match_task;
pcre2_match_data *mdata;
PCRE2_UCHAR *buf;
PCRE2_SIZE len;
int ret;
char *msg;
uintptr_t snap;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(regex, VMOD_PCRE2_REGEX_MAGIC);
CHECK_UINT32_RANGE(ref, regex->vcl_name, ".backref()", fallback);
match_task = VRT_priv_task(ctx, regex);
if (match_task == NULL) {
VERR(ctx, "%s.backref(%ld) called without prior match",
regex->vcl_name, ref);
return fallback;
}
WS_Assert_Allocated(ctx->ws, match_task->priv, 0);
mdata = match_task->priv;
if ((ret = pcre2_substring_get_bynumber(mdata, (uint32_t)ref, &buf,
&len)) == 0) {
WS_Assert_Allocated(ctx->ws, buf, len + 1);
return (VCL_STRING)buf;
}
snap = WS_Snapshot(ctx->ws);
if ((msg = WS_Printf(ctx->ws, "in %s.backref(%ld)", regex->vcl_name,
ref)) == NULL)
msg = "";
report_pcre2_err(ctx, ret, msg, "");
WS_Reset(ctx->ws, snap);
return fallback;
}
/* Functions */
VCL_BOOL
......
......@@ -39,6 +39,8 @@ $Method BOOL .match(PRIV_CALL, PRIV_TASK, STRING subject, INT len=0,
BOOL no_utf_check = 0, ENUM {HARD, SOFT} partial=0,
INT recursion_limit=0)
$Method STRING .backref(INT ref, STRING fallback = "**BACKREF METHOD FAILED**")
$Function BOOL config_bool(ENUM {JIT, STACKRECURSE, UNICODE})
$Function STRING config_str(ENUM {BSR, JITTARGET, NEWLINE, UNICODE_VERSION,
......
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