Commit a6c974d4 authored by Geoff Simmons's avatar Geoff Simmons

consolidate common code for sub, suball and extract

parent 7b38a91b
......@@ -83,6 +83,12 @@ static const void *match_failed = (void *) &c;
static size_t match_sz;
static const char * const rewrite_name[] = {
[SUB] = "sub",
[SUBALL] = "suball",
[EXTRACT] = "extract",
};
static void
errmsg(VRT_CTX, const char *fmt, ...)
{
......@@ -236,11 +242,11 @@ namedref(VRT_CTX, vre2 * restrict vre2, VCL_STRING name, VCL_STRING fallback,
#undef ERR_PREFIX
#define ERR_PREFIX \
"sub(text=\"%.40s\", rewrite=\"%.40s\", fallback=\"%.40s\"): "
"%s(text=\"%.40s\", rewrite=\"%.40s\", fallback=\"%.40s\"): "
static VCL_STRING
sub(VRT_CTX, vre2 * restrict vre2, const int all, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
rewritef(VRT_CTX, vre2 * restrict vre2, const rewrite_e mode, VCL_STRING text,
VCL_STRING rewrite, VCL_STRING fallback)
{
int match = 0;
size_t bytes, len;
......@@ -250,49 +256,15 @@ sub(VRT_CTX, vre2 * restrict vre2, const int all, VCL_STRING text,
ret = WS_Snapshot(ctx->ws);
bytes = WS_Reserve(ctx->ws, 0);
if (bytes == 0) {
VERR(ctx, ERR_PREFIX "workspace overflow", text, rewrite,
fallback);
VERR(ctx, ERR_PREFIX "workspace overflow", rewrite_name[mode],
text, rewrite, fallback);
return fallback;
}
if ((err = vre2_replace(vre2, all, text, rewrite, ret, bytes, &match,
if ((err = vre2_rewrite(vre2, mode, text, rewrite, ret, bytes, &match,
&len))
!= NULL) {
VERR(ctx, ERR_PREFIX "%s", 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
#define ERR_PREFIX \
"extract(text=\"%.40s\", rewrite=\"%.40s\", fallback=\"%.40s\"): "
static VCL_STRING
extract(VRT_CTX, vre2 * restrict vre2, VCL_STRING text, VCL_STRING rewrite,
VCL_STRING fallback)
{
int match = 0;
size_t bytes, len;
char *ret;
const char *err;
ret = WS_Snapshot(ctx->ws);
bytes = WS_Reserve(ctx->ws, 0);
if (bytes == 0) {
VERR(ctx, ERR_PREFIX "workspace overflow", text, rewrite,
fallback);
return fallback;
}
if ((err = vre2_extract(vre2, text, rewrite, ret, bytes, &match, &len))
!= NULL) {
VERR(ctx, ERR_PREFIX "%s", text, rewrite, fallback, err);
VERR(ctx, ERR_PREFIX "%s", rewrite_name[mode], text, rewrite,
fallback, err);
WS_Release(ctx->ws, 0);
return fallback;
}
......@@ -461,47 +433,48 @@ vmod_regex_namedref(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING name,
#undef ERR_PREFIX
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)
sub_method(VRT_CTX, const rewrite_e mode, 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.%s(): fallback is undefined", re->vcl_name,
mname);
if (all)
rewrite_name[mode]);
if (mode == SUBALL)
return "**SUBALL METHOD FAILED**";
else
return "**SUB METHOD FAILED**";
}
if (text == NULL) {
VERR(ctx, "%s.%s(text=<undefined>, fallback=\"%.40s\"): "
"text is undefined", re->vcl_name, mname, fallback);
"text is undefined", re->vcl_name, rewrite_name[mode],
fallback);
return fallback;
}
if (rewrite == NULL) {
VERR(ctx, "%s.%s(text=\"%.40s\", rewrite=<undefined>, "
"fallback=\"%.40s\"): rewrite is undefined", re->vcl_name,
mname, text, fallback);
rewrite_name[mode], text, fallback);
return fallback;
}
return sub(ctx, re->vre2, all, text, rewrite, fallback);
return rewritef(ctx, re->vre2, mode, 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);
return sub_method(ctx, SUB, 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);
return sub_method(ctx, SUBALL, re, text, rewrite, fallback);
}
VCL_STRING
......@@ -526,7 +499,7 @@ vmod_regex_extract(VRT_CTX, struct vmod_re2_regex *re, VCL_STRING text,
return fallback;
}
return extract(ctx, re->vre2, text, rewrite, fallback);
return rewritef(ctx, re->vre2, EXTRACT, text, rewrite, fallback);
}
/* Object set */
......@@ -816,40 +789,42 @@ vmod_namedref(VRT_CTX, struct vmod_priv *priv, VCL_STRING name,
#define ERR_PREFIX "re2.%s(pattern=\"%.40s\", text=\"%.40s\", rewrite=\"%.40s\", fallback=\"%.40s\"): "
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)
sub_function(VRT_CTX, const rewrite_e mode, 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) {
VERR(ctx, "re2.%s(): fallback is undefined", fname);
if (all)
VERR(ctx, "re2.%s(): fallback is undefined",
rewrite_name[mode]);
if (mode == SUBALL)
return "**SUBALL FUNCTION FAILED**";
else
return "**SUB FUNCTION FAILED**";
}
if (pattern == NULL) {
VERR(ctx, "re2.%s(pattern=<undefined>, fallback=\"%.40s\"): "
"pattern is undefined", fname, fallback);
"pattern is undefined", rewrite_name[mode], fallback);
return fallback;
}
if (text == NULL) {
VERR(ctx, "re2.%s(pattern=\"%s\", text=<undefined>, "
"fallback=\"%.40s\"): text is undefined", fname, pattern,
fallback);
"fallback=\"%.40s\"): text is undefined",
rewrite_name[mode], pattern, fallback);
return fallback;
}
if (rewrite == NULL) {
VERR(ctx, "re2.%s(pattern=\"%.40s\", text=\"%.40s\", "
"rewrite=<undefined>, fallback=\"%.40s\"): "
"rewrite is undefined", fname, pattern, text, fallback);
"rewrite is undefined", rewrite_name[mode], pattern, text,
fallback);
return fallback;
}
......@@ -858,12 +833,13 @@ sub_function(VRT_CTX, const char * const restrict fname, const int all,
case_sensitive, perl_classes, word_boundary,
one_line))
!= NULL) {
VERR(ctx, ERR_PREFIX "Cannot compile '%s': %s", fname, pattern,
text, rewrite, fallback, pattern, err);
VERR(ctx, ERR_PREFIX "Cannot compile '%s': %s",
rewrite_name[mode], pattern, text, rewrite, fallback,
pattern, err);
vre2_fini(&vre2);
return fallback;
}
ret = sub(ctx, vre2, all, text, rewrite, fallback);
ret = rewritef(ctx, vre2, mode, text, rewrite, fallback);
vre2_fini(&vre2);
return ret;
}
......@@ -878,22 +854,22 @@ vmod_sub(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
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,
return sub_function(ctx, SUB, 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)
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,
return sub_function(ctx, SUBALL, 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);
}
......@@ -945,7 +921,7 @@ vmod_extract(VRT_CTX, VCL_STRING pattern, VCL_STRING text, VCL_STRING rewrite,
vre2_fini(&vre2);
return fallback;
}
ret = extract(ctx, vre2, text, rewrite, fallback);
ret = rewritef(ctx, vre2, EXTRACT, text, rewrite, fallback);
vre2_fini(&vre2);
return ret;
}
......
......@@ -182,12 +182,31 @@ vre2_get_group(vre2 *vre2, const char * const name, int * const refnum)
CATCHALL
}
static inline const char *
copy_on_match(const string& result, const int match, char * const dest,
const size_t bytes, size_t * const len)
const char *
vre2_rewrite(vre2 *vre2, const rewrite_e mode, const char * const text,
const char * const rewrite, char * const dest, const size_t bytes,
int * const match, size_t * const len)
{
try {
if (!match)
string result;
switch(mode) {
case SUB:
result = text;
*match = vre2->replace(&result, rewrite);
break;
case SUBALL:
result = text;
*match = vre2->global_replace(&result, rewrite);
break;
case EXTRACT:
*match = vre2->extract(&result, text, rewrite);
break;
default:
throw runtime_error("illegal mode");
}
if (!*match)
return NULL;
if (result.size() + 1 > bytes)
throw runtime_error("insufficient workspace");
......@@ -199,35 +218,6 @@ copy_on_match(const string& result, const int match, char * const dest,
CATCHALL
}
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)
{
try {
string t(text);
if (all)
*match = vre2->global_replace(&t, rewrite);
else
*match = vre2->replace(&t, rewrite);
return copy_on_match(t, *match, dest, bytes, len);
}
CATCHALL
}
const char *
vre2_extract(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 out;
*match = vre2->extract(&out, text, rewrite);
return copy_on_match(out, *match, dest, bytes, len);
}
CATCHALL
}
const char *
vre2_fini(vre2 **vre2)
{
......
......@@ -57,6 +57,12 @@ public:
typedef struct vre2 vre2;
#endif
typedef enum {
SUB = 0,
SUBALL,
EXTRACT
} rewrite_e;
#ifdef __cplusplus
extern "C" {
#endif
......@@ -78,15 +84,11 @@ 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 int all,
const char *vre2_rewrite(vre2 *vre2, const rewrite_e mode,
const char * const text,
const char * const rewrite,
char * const dest, const size_t bytes,
int * const match, size_t * const len);
const char *vre2_extract(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