summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2015-02-12 14:30:53 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2015-02-12 14:30:53 (GMT)
commit133e104d9efac43c0cf243207c2c5eaf0343bced (patch) (unidiff)
tree64399bcc3d6b33de2fb911d291ba90656b028fc1
parentc36a2210ed6cd53c5c65418fa9c20ac22dec8c59 (diff)
downloadvmod-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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac18
-rw-r--r--src/variable.c139
-rw-r--r--tests/batchset.at6
3 files changed, 101 insertions, 62 deletions
diff --git a/configure.ac b/configure.ac
index 2fa32f6..f21fcfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,24 +108,6 @@ if test -z "$VMODDIR"; then
108 VMODDIR='$(libdir)/varnish/mods' 108 VMODDIR='$(libdir)/varnish/mods'
109fi 109fi
110 110
111###########
112# Check for db.h and libdb
113#
114AC_CHECK_HEADER([db.h],,[AC_MSG_ERROR([Required header file db.h not found])])
115
116AC_CHECK_LIB(db, db_create,
117 [LIBS="$LIBS -ldb"
118 AC_RUN_IFELSE(
119 [AC_LANG_PROGRAM([#include "db.h"],
120 [int v_major, v_minor, v_patch;
121 db_version(&v_major, &v_minor, &v_patch);
122 return !(v_major == DB_VERSION_MAJOR
123 && v_minor == DB_VERSION_MINOR
124 && v_patch == DB_VERSION_PATCH);
125 ])],
126 [],
127 [AC_MSG_ERROR([header file db.h is not the same version as libdb])])])
128
129AC_CONFIG_COMMANDS([status],[ 111AC_CONFIG_COMMANDS([status],[
130delim="-------------------------------------------------------------------" 112delim="-------------------------------------------------------------------"
131echo "" 113echo ""
diff --git a/src/variable.c b/src/variable.c
index 6403c1a..9442b6b 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -500,7 +500,8 @@ log_error(const char *fmt, ...)
500struct vardef { 500struct vardef {
501 struct vardef *next; 501 struct vardef *next;
502 enum variable_type type; 502 enum variable_type type;
503 char name[1]; 503 char *name;
504 char *repl;
504}; 505};
505 506
506static void 507static void
@@ -570,6 +571,51 @@ str2duration(const char *str)
570 return *p ? 0 : r; 571 return *p ? 0 : r;
571 } 572 }
572 573
574char *
575bref_expand(const char *str, const char *input, pcre *re,
576 int ovsize, int *ovector)
577{
578 size_t rlen = 0;
579 char *rbase = NULL;
580 char *rptr;
581 int nm = 2*ovsize/3;
582 const char *p;
583
584 for (p = str; *p; ) {
585 if (*p == '\\' && strchr("123456789", p[1])) {
586 int n = 2*(p[1] - '0');
587 if (n < nm) {
588 rlen += ovector[n+1] - ovector[n];
589 p += 2;
590 continue;
591 }
592 }
593 ++p;
594 ++rlen;
595 }
596 rbase = malloc(rlen + 1);
597 AN(rbase);
598 p = str;
599 rptr = rbase;
600 while (*p) {
601 if (*p == '\\' && strchr("123456789", p[1])) {
602 int n = 2*(p[1] - '0');
603 if (n < nm) {
604 memcpy(rptr, input + ovector[n],
605 ovector[n+1] - ovector[n]);
606 rptr += ovector[n+1] - ovector[n];
607 p += 2;
608 continue;
609 }
610 }
611
612 *rptr++ = *p++;
613 }
614 *rptr = 0;
615
616 return rbase;
617}
618
573VCL_VOID 619VCL_VOID
574vmod_batchset(VARIABLE_CTX ctx, 620vmod_batchset(VARIABLE_CTX ctx,
575 VCL_STRING vars, VCL_STRING rxs, VCL_STRING input) 621 VCL_STRING vars, VCL_STRING rxs, VCL_STRING input)
@@ -598,50 +644,63 @@ vmod_batchset(VARIABLE_CTX ctx,
598 } 644 }
599 645
600 while (*v) { 646 while (*v) {
601 size_t n = strcspn(v, "="); 647 char const *nameptr = v;
648 size_t n = strcspn(v, ":=,");
649 size_t namelen;
650 char const *replptr;
651 size_t repllen;
652 char rbuf[3];
653 enum variable_type type;
654 int delim;
655
656 namelen = n;
602 657
603 if (!v[n]) { 658 v += n;
604 log_error("variable.batchset: vars argument invalid near %s", 659 delim = *v ? *v++ : 0;
605 v); 660
606 vardef_free(head); 661 if (delim == ':') {
607 return; 662 n = strcspn(v, "=,");
663 type = str2type(v, n);
664 v += n;
665 delim = *v ? *v++ : 0;
666 } else
667 type = variable_string;
668
669 if (delim == '=') {
670 n = strcspn(v, ",");
671 replptr = v;
672 repllen = n;
673 v += n;
674 delim = *v ? *v++ : 0;
675 } else {
676 rbuf[0] = '\\';
677 rbuf[1] = count + '1';
678 rbuf[2] = 0;
679 replptr = rbuf;
680 repllen = 2;
608 } 681 }
609 def = malloc(sizeof(def[0]) + n); 682
683 def = malloc(sizeof(def[0]) + namelen + repllen + 2);
610 def->next = NULL; 684 def->next = NULL;
611 memcpy(def->name, v, n);
612 def->name[n] = 0;
613 if (tail) 685 if (tail)
614 tail->next = def; 686 tail->next = def;
615 else 687 else
616 head = def; 688 head = def;
617 tail = def; 689 tail = def;
618 ++count; 690 ++count;
619 691 def->type = type;
620 v += n + 1; 692 def->name = (char*)(def + 1);
621 if (!*v) { 693 memcpy(def->name, nameptr, namelen);
622 log_error("variable.batchset: no type for %s", def->name); 694 def->name[namelen] = 0;
623 vardef_free(head); 695 def->repl = def->name + namelen + 1;
624 return; 696 memcpy(def->repl, replptr, repllen);
625 } 697 def->repl[repllen] = 0;
626
627 n = strcspn(v, ",");
628 def->type = str2type(v, n);
629 if (def->type == variable_unset) {
630 log_error("variable.batchset: invalid type for %s",
631 def->name);
632 vardef_free(head);
633 return;
634 }
635
636 v += n;
637 if (*v)
638 ++v;
639 } 698 }
640 699
641 re = pcre_compile(rxs, cflags, &error_ptr, &error_offset, NULL); 700 re = pcre_compile(rxs, cflags, &error_ptr, &error_offset, NULL);
642 if (!re) { 701 if (!re) {
643 log_error("variable.batchset: %s: compilation failed near %s: %s", 702 log_error("variable.batchset: %s: compilation failed near %s: %s",
644 rxs, rxs + error_offset, error_ptr); 703 rxs, rxs + error_offset, error_ptr);
645 vardef_free(head); 704 vardef_free(head);
646 return; 705 return;
647 } 706 }
@@ -673,16 +732,8 @@ vmod_batchset(VARIABLE_CTX ctx,
673 return; 732 return;
674 } 733 }
675 734
676 for (def = head, i = 1; def; def = def->next, i++) { 735 for (def = head; def; def = def->next, i++) {
677 const char *s; 736 char *s = bref_expand(def->repl, input, re, ovsize, ovector);
678
679 rc = pcre_get_substring(input, ovector, ovsize, i, &s);
680 if (rc < 0) {
681 log_error("variable.batchset: %s(%s) can't get subexpr #%d: %d",
682 rxs, input, i, rc);
683 vardef_free(head);
684 return;
685 }
686 737
687 switch (def->type) { 738 switch (def->type) {
688 case variable_string: 739 case variable_string:
@@ -704,6 +755,7 @@ vmod_batchset(VARIABLE_CTX ctx,
704 value.i = 0; 755 value.i = 0;
705 } else 756 } else
706 value.i = lval; 757 value.i = lval;
758 free(s);
707 break; 759 break;
708 case variable_real: 760 case variable_real:
709 errno = 0; 761 errno = 0;
@@ -716,11 +768,13 @@ vmod_batchset(VARIABLE_CTX ctx,
716 rxs, input, i, strerror(errno)); 768 rxs, input, i, strerror(errno));
717 value.r = 0; 769 value.r = 0;
718 } 770 }
771 free(s);
719 break; 772 break;
720 773
721 case variable_duration: 774 case variable_duration:
722 value.d = str2duration(s); 775 value.d = str2duration(s);
723 break; 776 free(s);
777 break;
724 default: 778 default:
725 abort(); 779 abort();
726 } 780 }
@@ -731,3 +785,4 @@ vmod_batchset(VARIABLE_CTX ctx,
731 free(ovector); 785 free(ovector);
732 vardef_free(head); 786 vardef_free(head);
733} 787}
788
diff --git a/tests/batchset.at b/tests/batchset.at
index be07cae..506fe78 100644
--- a/tests/batchset.at
+++ b/tests/batchset.at
@@ -19,17 +19,19 @@ AT_KEYWORDS(batchset)
19 19
20AT_VARNISHTEST([ 20AT_VARNISHTEST([
21sub vcl_recv { 21sub vcl_recv {
22 variable.batchset("y=i,x=s", "^/(\d+)/(.+)", req.url); 22 variable.batchset("y:i,x,time:d=\3s", "^/(\d+)/(.+)/(\d+)", req.url);
23} 23}
24sub vcl_deliver { 24sub vcl_deliver {
25 set resp.http.X-X = variable.get("x"); 25 set resp.http.X-X = variable.get("x");
26 set resp.http.X-Y = variable.get_int("y"); 26 set resp.http.X-Y = variable.get_int("y");
27 set resp.http.X-Time = variable.get_duration("time");
27} 28}
28],[ 29],[
29txreq -url /10/test 30txreq -url /10/test/60
30rxresp 31rxresp
31expect resp.http.X-X == "test" 32expect resp.http.X-X == "test"
32expect resp.http.X-Y == "10" 33expect resp.http.X-Y == "10"
34expect resp.http.X-Time == "60.000"
33]) 35])
34AT_CLEANUP 36AT_CLEANUP
35 37

Return to:

Send suggestions and report system problems to the System administrator.