diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-02-12 16:30:53 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-02-12 16:30:53 +0200 |
commit | 133e104d9efac43c0cf243207c2c5eaf0343bced (patch) | |
tree | 64399bcc3d6b33de2fb911d291ba90656b028fc1 | |
parent | c36a2210ed6cd53c5c65418fa9c20ac22dec8c59 (diff) | |
download | vmod-variable-133e104d9efac43c0cf243207c2c5eaf0343bced.tar.gz vmod-variable-133e104d9efac43c0cf243207c2c5eaf0343bced.tar.bz2 |
Improve batchset
The new syntax allows for supplying replacement patterns as in
variable.batchset("x:duration=\2s", ...
* configure.ac: Remove unneeded check
* src/variable.c (vardef): New member repl.
(bref_expand): New function.
(vmod_batchset): Change handling of vars string.
* tests/batchset.at: Update.
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | src/variable.c | 135 | ||||
-rw-r--r-- | tests/batchset.at | 6 |
3 files changed, 99 insertions, 60 deletions
diff --git a/configure.ac b/configure.ac index 2fa32f6..f21fcfb 100644 --- a/configure.ac +++ b/configure.ac @@ -110,20 +110,2 @@ fi -########### -# Check for db.h and libdb -# -AC_CHECK_HEADER([db.h],,[AC_MSG_ERROR([Required header file db.h not found])]) - -AC_CHECK_LIB(db, db_create, - [LIBS="$LIBS -ldb" - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([#include "db.h"], - [int v_major, v_minor, v_patch; - db_version(&v_major, &v_minor, &v_patch); - return !(v_major == DB_VERSION_MAJOR - && v_minor == DB_VERSION_MINOR - && v_patch == DB_VERSION_PATCH); - ])], - [], - [AC_MSG_ERROR([header file db.h is not the same version as libdb])])]) - AC_CONFIG_COMMANDS([status],[ diff --git a/src/variable.c b/src/variable.c index 6403c1a..9442b6b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -502,3 +502,4 @@ struct vardef { enum variable_type type; - char name[1]; + char *name; + char *repl; }; @@ -572,2 +573,47 @@ str2duration(const char *str) +char * +bref_expand(const char *str, const char *input, pcre *re, + int ovsize, int *ovector) +{ + size_t rlen = 0; + char *rbase = NULL; + char *rptr; + int nm = 2*ovsize/3; + const char *p; + + for (p = str; *p; ) { + if (*p == '\\' && strchr("123456789", p[1])) { + int n = 2*(p[1] - '0'); + if (n < nm) { + rlen += ovector[n+1] - ovector[n]; + p += 2; + continue; + } + } + ++p; + ++rlen; + } + rbase = malloc(rlen + 1); + AN(rbase); + p = str; + rptr = rbase; + while (*p) { + if (*p == '\\' && strchr("123456789", p[1])) { + int n = 2*(p[1] - '0'); + if (n < nm) { + memcpy(rptr, input + ovector[n], + ovector[n+1] - ovector[n]); + rptr += ovector[n+1] - ovector[n]; + p += 2; + continue; + } + } + + *rptr++ = *p++; + } + *rptr = 0; + + return rbase; +} + VCL_VOID @@ -600,14 +646,40 @@ vmod_batchset(VARIABLE_CTX ctx, while (*v) { - size_t n = strcspn(v, "="); + char const *nameptr = v; + size_t n = strcspn(v, ":=,"); + size_t namelen; + char const *replptr; + size_t repllen; + char rbuf[3]; + enum variable_type type; + int delim; - if (!v[n]) { - log_error("variable.batchset: vars argument invalid near %s", - v); - vardef_free(head); - return; + namelen = n; + + v += n; + delim = *v ? *v++ : 0; + + if (delim == ':') { + n = strcspn(v, "=,"); + type = str2type(v, n); + v += n; + delim = *v ? *v++ : 0; + } else + type = variable_string; + + if (delim == '=') { + n = strcspn(v, ","); + replptr = v; + repllen = n; + v += n; + delim = *v ? *v++ : 0; + } else { + rbuf[0] = '\\'; + rbuf[1] = count + '1'; + rbuf[2] = 0; + replptr = rbuf; + repllen = 2; } - def = malloc(sizeof(def[0]) + n); + + def = malloc(sizeof(def[0]) + namelen + repllen + 2); def->next = NULL; - memcpy(def->name, v, n); - def->name[n] = 0; if (tail) @@ -618,22 +690,9 @@ vmod_batchset(VARIABLE_CTX ctx, ++count; - - v += n + 1; - if (!*v) { - log_error("variable.batchset: no type for %s", def->name); - vardef_free(head); - return; - } - - n = strcspn(v, ","); - def->type = str2type(v, n); - if (def->type == variable_unset) { - log_error("variable.batchset: invalid type for %s", - def->name); - vardef_free(head); - return; - } - - v += n; - if (*v) - ++v; + def->type = type; + def->name = (char*)(def + 1); + memcpy(def->name, nameptr, namelen); + def->name[namelen] = 0; + def->repl = def->name + namelen + 1; + memcpy(def->repl, replptr, repllen); + def->repl[repllen] = 0; } @@ -675,12 +734,4 @@ vmod_batchset(VARIABLE_CTX ctx, - for (def = head, i = 1; def; def = def->next, i++) { - const char *s; - - rc = pcre_get_substring(input, ovector, ovsize, i, &s); - if (rc < 0) { - log_error("variable.batchset: %s(%s) can't get subexpr #%d: %d", - rxs, input, i, rc); - vardef_free(head); - return; - } + for (def = head; def; def = def->next, i++) { + char *s = bref_expand(def->repl, input, re, ovsize, ovector); @@ -706,2 +757,3 @@ vmod_batchset(VARIABLE_CTX ctx, value.i = lval; + free(s); break; @@ -718,2 +770,3 @@ vmod_batchset(VARIABLE_CTX ctx, } + free(s); break; @@ -722,2 +775,3 @@ vmod_batchset(VARIABLE_CTX ctx, value.d = str2duration(s); + free(s); break; @@ -733 +787,2 @@ vmod_batchset(VARIABLE_CTX ctx, } + diff --git a/tests/batchset.at b/tests/batchset.at index be07cae..506fe78 100644 --- a/tests/batchset.at +++ b/tests/batchset.at @@ -21,3 +21,3 @@ AT_VARNISHTEST([ sub vcl_recv { - variable.batchset("y=i,x=s", "^/(\d+)/(.+)", req.url); + variable.batchset("y:i,x,time:d=\3s", "^/(\d+)/(.+)/(\d+)", req.url); } @@ -26,5 +26,6 @@ sub vcl_deliver { set resp.http.X-Y = variable.get_int("y"); + set resp.http.X-Time = variable.get_duration("time"); } ],[ -txreq -url /10/test +txreq -url /10/test/60 rxresp @@ -32,2 +33,3 @@ expect resp.http.X-X == "test" expect resp.http.X-Y == "10" +expect resp.http.X-Time == "60.000" ]) |