[master] d9f31889b VMOD blob uses STRANDS instead of STRING_LIST.
Geoff Simmons
geoff at uplex.de
Thu Aug 16 20:11:05 UTC 2018
commit d9f31889b3ff4b9a88c96f83e67be1df3f33071e
Author: Geoff Simmons <geoff at uplex.de>
Date: Thu Aug 16 22:09:18 2018 +0200
VMOD blob uses STRANDS instead of STRING_LIST.
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 4124100f4..e17dd8960 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;
ssize_t len = 0;
- va_list ap2;
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;
@@ -130,7 +131,6 @@ hex_decode(const enum encoding dec, char *restrict const buf,
break;
len += s - b;
}
- va_end(ap2);
if (len == 0)
return 0;
@@ -150,8 +150,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 0a7e652d5..a6514dd2e 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 632580e91..013533ae9 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