[6.0] 4f17aa8c8 VMOD blob uses STRANDS instead of STRING_LIST.

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Wed Jul 3 14:40:10 UTC 2019


commit 4f17aa8c8076e84f7a43eda42b348b6b6552a3e6
Author: Geoff Simmons <geoff at uplex.de>
Date:   Thu Aug 16 22:09:18 2018 +0200

    VMOD blob uses STRANDS instead of STRING_LIST.
    
    Conflicts:
            lib/libvmod_blob/hex.c

diff --git a/lib/libvmod_blob/base64.c b/lib/libvmod_blob/base64.c
index 201702962..3bea94871 100644
--- a/lib/libvmod_blob/base64.c
+++ b/lib/libvmod_blob/base64.c
@@ -29,12 +29,12 @@
 #include "config.h"
 #include <errno.h>
 
-#include "base64.h"
-
 #include "vdef.h"
 #include "vrt.h"
 #include "vas.h"
 
+#include "base64.h"
+
 #define base64_l(l)		(((l) << 2) / 3)
 
 size_t
@@ -133,7 +133,7 @@ base64_encode(const enum encoding enc, const enum case_e kase,
 ssize_t
 base64_decode(const enum encoding dec, char *restrict const buf,
 	      const size_t buflen, ssize_t inlen,
-	      const char *const p, va_list ap)
+	      const struct strands *restrict const strings)
 {
 	const struct b64_alphabet *alpha = &b64_alphabet[dec];
 	char *dest = buf;
@@ -143,12 +143,14 @@ base64_decode(const enum encoding dec, char *restrict const buf,
 
 	AN(buf);
 	AN(alpha);
+	AN(strings);
 
 	if (inlen >= 0)
 		len = inlen;
 
-	for (const char *s = p; len > 0 && s != vrt_magic_string_end;
-	     s = va_arg(ap, const char *)) {
+	for (int i = 0; len > 0 && i < strings->n; i++) {
+		const char *s = strings->p[i];
+
 		if (s == NULL)
 			continue;
 		if (*s && term) {
diff --git a/lib/libvmod_blob/hex.c b/lib/libvmod_blob/hex.c
index 614404d9e..adcf94b24 100644
--- a/lib/libvmod_blob/hex.c
+++ b/lib/libvmod_blob/hex.c
@@ -30,13 +30,14 @@
 #include <ctype.h>
 #include <errno.h>
 
-#include "vmod_blob.h"
 #include "hex.h"
 
 #include "vdef.h"
 #include "vrt.h"
 #include "vas.h"
 
+#include "vmod_blob.h"
+
 const char hex_alphabet[][16] = {
 	"0123456789abcdef",
 	"0123456789ABCDEF"
@@ -103,20 +104,20 @@ hex_encode(const enum encoding enc, const enum case_e kase,
 ssize_t
 hex_decode(const enum encoding dec, char *restrict const buf,
 	   const size_t buflen, ssize_t n,
-	   const char *restrict const p, va_list ap)
+	   const struct strands *restrict const strings)
 {
 	char *dest = buf;
 	const char *b;
 	unsigned char extranib = 0;
-	size_t len = 0;
-	va_list ap2;
+	ssize_t len = 0;
 
 	AN(buf);
+	AN(strings);
 	assert(dec == HEX);
 
-	va_copy(ap2, ap);
-	for (const char *s = p; s != vrt_magic_string_end;
-	     s = va_arg(ap2, const char *)) {
+	for (int i = 0; i < strings->n; i++) {
+		const char *s = strings->p[i];
+
 		if (s == NULL)
 			continue;
 		b = s;
@@ -128,7 +129,6 @@ hex_decode(const enum encoding dec, char *restrict const buf,
 		}
 		len += s - b;
 	}
-	va_end(ap2);
 
 	if (len == 0)
 		return 0;
@@ -144,8 +144,9 @@ hex_decode(const enum encoding dec, char *restrict const buf,
 		len++;
 	}
 
-	for (const char *s = p; len > 0 && s != vrt_magic_string_end;
-	     s = va_arg(ap, const char *)) {
+	for (int i = 0; len > 0 && i < strings->n; i++) {
+		const char *s = strings->p[i];
+
 		if (s == NULL || *s == '\0')
 			continue;
 		if (extranib) {
diff --git a/lib/libvmod_blob/id.c b/lib/libvmod_blob/id.c
index d10e64250..1164e983d 100644
--- a/lib/libvmod_blob/id.c
+++ b/lib/libvmod_blob/id.c
@@ -30,12 +30,12 @@
 #include <string.h>
 #include <errno.h>
 
-#include "vmod_blob.h"
-
 #include "vdef.h"
 #include "vrt.h"
 #include "vas.h"
 
+#include "vmod_blob.h"
+
 size_t
 id_encode_l(size_t l)
 {
@@ -69,20 +69,21 @@ id_encode(const enum encoding enc, const enum case_e kase,
 ssize_t
 id_decode(const enum encoding enc,
 	  char *restrict const buf, const size_t buflen,
-	  ssize_t n, const char *restrict const p, va_list ap)
+	  ssize_t n, const struct strands *restrict const strings)
 {
 	char *dest = buf;
 	size_t outlen = 0, c = SIZE_MAX;
 
 	(void) enc;
 	AN(buf);
+	AN(strings);
 
 	if (n >= 0)
 		c = n;
 
-	for (const char *s = p; c > 0 && s != vrt_magic_string_end;
-	     s = va_arg(ap, const char *)) {
+	for (int i = 0; c > 0 && i < strings->n; i++) {
 		size_t len;
+		const char *s = strings->p[i];
 
 		if (s == NULL || *s == '\0')
 			continue;
diff --git a/lib/libvmod_blob/url.c b/lib/libvmod_blob/url.c
index 84f5d0f22..acb55a6bb 100644
--- a/lib/libvmod_blob/url.c
+++ b/lib/libvmod_blob/url.c
@@ -29,13 +29,14 @@
 #include "config.h"
 #include <errno.h>
 
-#include "vmod_blob.h"
 #include "hex.h"
 
 #include "vdef.h"
 #include "vrt.h"
 #include "vas.h"
 
+#include "vmod_blob.h"
+
 /* Decoder states */
 enum state_e {
 	NORMAL,
@@ -115,8 +116,8 @@ url_encode(const enum encoding enc, const enum case_e kase,
 
 ssize_t
 url_decode(const enum encoding dec, char *restrict const buf,
-	   const size_t buflen, ssize_t n, const char *restrict const p,
-	   va_list ap)
+	   const size_t buflen, ssize_t n,
+	   const struct strands *restrict const strings)
 {
 	char *dest = buf;
 	const char * const end = buf + buflen;
@@ -125,13 +126,15 @@ url_decode(const enum encoding dec, char *restrict const buf,
 	enum state_e state = NORMAL;
 
 	AN(buf);
+	AN(strings);
 	assert(dec == URL);
 
 	if (n >= 0 && (size_t)n < len)
 		len = n;
 
-	for (const char *s = p; len > 0 && s != vrt_magic_string_end;
-	     s = va_arg(ap, const char *)) {
+	for (int i = 0; len > 0 && i < strings->n; i++) {
+		const char *s = strings->p[i];
+
 		if (s == NULL || *s == '\0')
 			continue;
 		while (*s && len) {
diff --git a/lib/libvmod_blob/vmod.vcc b/lib/libvmod_blob/vmod.vcc
index 798989b52..1ea3716d4 100644
--- a/lib/libvmod_blob/vmod.vcc
+++ b/lib/libvmod_blob/vmod.vcc
@@ -176,7 +176,7 @@ affect alphabetic characters that are not percent-encoded.
 
 $Function BLOB decode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 			    HEX, URL} decoding="IDENTITY", INT length=0,
-		      STRING_LIST encoded)
+		      STRANDS encoded)
 
 Returns the BLOB derived from the string ``encoded`` according to the
 scheme specified by ``decoding``.
@@ -231,7 +231,7 @@ $Function STRING transcode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 			   ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 				 HEX, URL} encoding="IDENTITY",
 			   ENUM {LOWER, UPPER, DEFAULT} case="DEFAULT",
-			   INT length=0, STRING_LIST encoded)
+			   INT length=0, STRANDS encoded)
 
 Translates from one encoding to another, by first decoding the string
 ``encoded`` according to the scheme ``decoding``, and then returning
@@ -300,7 +300,7 @@ BLOB.
 
 $Object blob(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX,
 		   URL} decoding="IDENTITY",
-	     STRING_LIST encoded)
+	     STRANDS encoded)
 
 Creates an object that contains the BLOB derived from the string
 ``encoded`` according to the scheme ``decoding``.
diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c
index 08fd2ddf8..dfb03cafa 100644
--- a/lib/libvmod_blob/vmod_blob.c
+++ b/lib/libvmod_blob/vmod_blob.c
@@ -133,16 +133,15 @@ parse_case(VCL_ENUM e)
 
 
 static inline size_t
-decode_l_va(enum encoding dec, const char * const p, va_list ap)
+decode_l(enum encoding dec, VCL_STRANDS s)
 {
 	size_t len = 0;
 
 	AENC(dec);
 
-	for (const char *s = p; s != vrt_magic_string_end;
-	     s = va_arg(ap, const char *))
-		if (s != NULL && *s != '\0')
-			len += strlen(s);
+	for (int i = 0; i < s->n; i++)
+		if (s->p[i] != NULL && *s->p[i] != '\0')
+			len += strlen(s->p[i]);
 
 	return(func[dec].decode_l(len));
 }
@@ -185,11 +184,10 @@ check_enc_case(VRT_CTX, VCL_ENUM encs, VCL_ENUM case_s, enum encoding enc,
 
 VCL_VOID v_matchproto_(td_blob_blob__init)
 vmod_blob__init(VRT_CTX, struct vmod_blob_blob **blobp, const char *vcl_name,
-		VCL_ENUM decs, const char *p, ...)
+		VCL_ENUM decs, VCL_STRANDS strings)
 {
 	struct vmod_blob_blob *b;
 	enum encoding dec = parse_encoding(decs);
-	va_list ap;
 	ssize_t len;
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
@@ -197,6 +195,7 @@ vmod_blob__init(VRT_CTX, struct vmod_blob_blob **blobp, const char *vcl_name,
 	AZ(*blobp);
 	AN(vcl_name);
 	AENC(dec);
+	AN(strings);
 
 	ALLOC_OBJ(b, VMOD_BLOB_MAGIC);
 	AN(b);
@@ -204,9 +203,7 @@ vmod_blob__init(VRT_CTX, struct vmod_blob_blob **blobp, const char *vcl_name,
 	b->blob.free = NULL;
 	AZ(pthread_mutex_init(&b->lock, NULL));
 
-	va_start(ap, p);
-	len = decode_l_va(dec, p, ap);
-	va_end(ap);
+	len = decode_l(dec, strings);
 	if (len == 0) {
 		b->blob.len = 0;
 		b->blob.priv = NULL;
@@ -220,17 +217,15 @@ vmod_blob__init(VRT_CTX, struct vmod_blob_blob **blobp, const char *vcl_name,
 		return;
 	}
 
-	va_start(ap, p);
 	errno = 0;
-	len = func[dec].decode(dec, b->blob.priv, len, -1, p, ap);
-	va_end(ap);
+	len = func[dec].decode(dec, b->blob.priv, len, -1, strings);
 
 	if (len == -1) {
 		assert(errno == EINVAL);
 		free(b->blob.priv);
 		b->blob.priv = NULL;
 		VERR(ctx, "cannot create blob %s, illegal encoding beginning "
-		    "with \"%s\"", vcl_name, p);
+		    "with \"%s\"", vcl_name, strings->p[0]);
 		return;
 	}
 	if (len == 0) {
@@ -331,31 +326,10 @@ vmod_blob__fini(struct vmod_blob_blob **blobp)
 
 /* Functions */
 
-static inline const char *
-find_nonempty_va(const char *restrict *p, va_list ap)
-{
-	const char *q;
-
-	/* find first non-empty vararg */
-	for (; *p == vrt_magic_string_end || *p == NULL || **p == '\0';
-	     *p = va_arg(ap, char *))
-		if (*p == vrt_magic_string_end)
-			return (vrt_magic_string_end);
-
-	/* find next non-empty vararg */
-	for (q = va_arg(ap, const char *);
-	     q != vrt_magic_string_end && (q == NULL || *q == '\0');
-	     q = va_arg(ap, const char *))
-		;
-
-	return (q);
-}
-
 VCL_BLOB v_matchproto_(td_blob_decode)
-vmod_decode(VRT_CTX, VCL_ENUM decs, VCL_INT length, const char *p, ...)
+vmod_decode(VRT_CTX, VCL_ENUM decs, VCL_INT length, VCL_STRANDS strings)
 {
 	enum encoding dec = parse_encoding(decs);
-	va_list ap;
 	struct vmod_priv *b;
 	char *buf;
 	uintptr_t snap;
@@ -364,6 +338,7 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, VCL_INT length, const char *p, ...)
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	AENC(dec);
+	AN(strings);
 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
 
 	snap = WS_Snapshot(ctx->ws);
@@ -377,13 +352,11 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, VCL_INT length, const char *p, ...)
 
 	if (length <= 0)
 		length = -1;
-	va_start(ap, p);
 	errno = 0;
-	len = func[dec].decode(dec, buf, space, length, p, ap);
-	va_end(ap);
+	len = func[dec].decode(dec, buf, space, length, strings);
 
 	if (len == -1) {
-		err_decode(ctx, p);
+		err_decode(ctx, strings->p[0]);
 		WS_Release(ctx->ws, 0);
 		WS_Reset(ctx->ws, snap);
 		return NULL;
@@ -450,17 +423,17 @@ vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_ENUM case_s, VCL_BLOB b)
 
 VCL_STRING v_matchproto_(td_blob_transcode)
 vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, VCL_ENUM case_s,
-	       VCL_INT length, const char *p, ...)
+	       VCL_INT length, VCL_STRANDS strings)
 {
 	enum encoding dec = parse_encoding(decs);
 	enum encoding enc = parse_encoding(encs);
 	enum case_e kase = parse_case(case_s);
-	va_list ap;
 	struct vmod_priv b;
 	VCL_STRING r;
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
+	AN(strings);
 
 	AENC(dec);
 	AENC(enc);
@@ -472,9 +445,7 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, VCL_ENUM case_s,
 	 * Allocate space for the decoded blob on the stack
 	 * ignoring the limitation imposed by n
 	 */
-	va_start(ap, p);
-	size_t l = decode_l_va(dec, p, ap);
-	va_end(ap);
+	size_t l = decode_l(dec, strings);
 	if (l == 0)
 		return "";
 	/* XXX: handle stack overflow? */
@@ -484,39 +455,28 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, VCL_ENUM case_s,
 
 	if (length <= 0)
 		length = -1;
-	va_start(ap, p);
 	errno = 0;
-	b.len = func[dec].decode(dec, buf, l, length, p, ap);
-	va_end(ap);
+	b.len = func[dec].decode(dec, buf, l, length, strings);
 
 	if (b.len == -1) {
-		err_decode(ctx, p);
+		err_decode(ctx, strings->p[0]);
 		return NULL;
 	}
 
 	/*
 	 * If the encoding and decoding are the same, and the decoding was
-	 * legal, just return the string, if there was only one in the
-	 * STRING_LIST, or else the concatenated string.
+	 * legal, just return the concatenated string.
 	 * For encodings with hex digits, we cannot assume the same result.
 	 * since the call may specify upper- or lower-case that differs
 	 * from the encoded string.
 	 */
-	if (length == -1 && enc == dec && !encodes_hex(enc)) {
-		const char *q, *pp = p;
-		va_start(ap, p);
-		q = find_nonempty_va(&pp, ap);
-		va_end(ap);
-
-		if (pp == vrt_magic_string_end)
-			return "";
-
-		if (q == vrt_magic_string_end)
-			return pp;
-
-		r = VRT_String(ctx->ws, NULL, p, ap);
-		return r;
-	}
+	if (length == -1 && enc == dec && !encodes_hex(enc))
+		/*
+		 * Returns NULL and invokes VCL failure on workspace
+		 * overflow. If there is only one string already in the
+		 * workspace, then it is re-used.
+		 */
+		return (VRT_CollectStrands(ctx, strings));
 
 	r = encode(ctx, enc, kase, &b);
 	return (r);
diff --git a/lib/libvmod_blob/vmod_blob.h b/lib/libvmod_blob/vmod_blob.h
index e47dff8e7..032f59986 100644
--- a/lib/libvmod_blob/vmod_blob.h
+++ b/lib/libvmod_blob/vmod_blob.h
@@ -26,8 +26,9 @@
  *
  */
 
+/* vrt.h must be included before this header (for struct strands). */
+
 #include <stdlib.h>
-#include <stdarg.h>
 #include <sys/types.h>
 
 enum encoding {
@@ -86,19 +87,18 @@ ssize_t encode_f(const enum encoding enc, const enum case_e kase,
 
 /*
  * General interface for a decoder: decode the concatenation of strings
- * in p and ap (obtained from a STRING_LIST) into buf, and return the
- * length of decoded data.
+ * (obtained from STRANDS) into buf, and return the length of decoded
+ * data.
  *
  * dec: decoding enum (from parse_encoding.h)
  * buf: destination of the decoded data
  * buflen: maximum length available at buf
  * inlen: maximum length to read or -1 to read up to \0
- * p, ap: strings obtained from a VCL STRING_LIST
+ * strings: strings obtained from VCL STRANDS
  *
- * The regions pointed to by buf and any of the strings in p or ap MUST
- * NOT overlap (per restrict).
- * Note that the p,ap list is terminated by vrt_magic_string_end, and
- * any member of the list may be NULL or empty.
+ * The regions pointed to by buf and strings MUST NOT overlap (per
+ * restrict).
+ * Note that any member of the strings list may be NULL or empty.
  *
  * Returns:
  * -1, if there is insufficient space at buf, or if the decoding is
@@ -110,7 +110,7 @@ ssize_t encode_f(const enum encoding enc, const enum case_e kase,
 typedef
 ssize_t decode_f(const enum encoding dec, char *restrict const buf,
 		 const size_t buflen, const ssize_t inlen,
-		 const char *restrict const p, va_list ap);
+		 const struct strands *restrict const strings);
 
 /* id.c */
 len_f	 id_encode_l;


More information about the varnish-commit mailing list