[master] 4113c8037 Add functions to treat a WS as a VSB.

Poul-Henning Kamp phk at FreeBSD.org
Mon Feb 10 09:15:08 UTC 2020


commit 4113c8037aab183059c0e6bce32de7530823ba79
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Feb 10 09:13:32 2020 +0000

    Add functions to treat a WS as a VSB.
    
    Usage pattern:
    
         struct vsb vsb[1];
         char *p;
    
         WS_VSB_new(vsb, ctx->ws);
         VSB_printf(vsb, "blablabla");
         p = WS_VSB_finish(vsb);
         if (p == NULL)
                 return (FAILURE);

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 360855e44..e83096935 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -795,6 +795,9 @@ void *WS_Printf(struct ws *ws, const char *fmt, ...) v_printflike_(2, 3);
 int WS_Inside(const struct ws *, const void *, const void *);
 void WS_Assert_Allocated(const struct ws *ws, const void *ptr, ssize_t len);
 
+void WS_VSB_new(struct vsb *, struct ws *);
+char *WS_VSB_finish(struct vsb *, struct ws *);
+
 static inline char*
 WS_Front(const struct ws *ws)
 {
diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index f224b9ffd..7a4b07ae5 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -440,63 +440,41 @@ VRT_Strands(char *d, size_t dl, VCL_STRANDS s)
 VCL_STRING
 VRT_StrandsWS(struct ws *ws, const char *h, VCL_STRANDS s)
 {
-	char *b;
-	const char *q = NULL, *e;
-	VCL_STRING r;
-	unsigned u, x;
+	const char *q = NULL;
+	struct vsb vsb[1];
 	int i;
 
+	WS_Assert(ws);
 	AN(s);
-	u = WS_ReserveAll(ws);
 
-	for (i = 0; i < s->n; i++)
+	for (i = 0; i < s->n; i++) {
 		if (s->p[i] != NULL && *s->p[i] != '\0') {
 			q = s->p[i];
 			break;
 		}
-
-	if (h != NULL && q == NULL && WS_Inside(ws, h, NULL)) {
-		WS_Release(ws, 0);
-		return (h);
 	}
 
-	if (h == NULL) {
-		if (q == NULL) {
-			WS_Release(ws, 0);
+	if (q == NULL) {
+		if (h == NULL)
 			return ("");
-		}
-		if (WS_Inside(ws, q, NULL)) {
-			for (i++; i < s->n; i++)
-				if (s->p[i] != NULL && *s->p[i] != '\0')
-					break;
-			if (i == s->n) {
-				WS_Release(ws, 0);
-				return (q);
-			}
-		}
+		if (WS_Inside(ws, h, NULL))
+			return (h);
+	} else if (h == NULL && WS_Inside(ws, q, NULL)) {
+		for (i++; i < s->n; i++)
+			if (s->p[i] != NULL && *s->p[i] != '\0')
+				break;
+		if (i == s->n)
+			return (q);
 	}
 
-	b = WS_Front(ws);
-	e = b + u;
-
-	if (h != NULL) {
-		x = strlen(h);
-		if (b + x < e)
-			memcpy(b, h, x);
-		b += x;
-		if (b < e)
-			*b = ' ';
-		b++;
-	}
-	r = VRT_Strands(b, e > b ? e - b : 0, s);
-	if (r == NULL || r == e) {
-		WS_MarkOverflow(ws);
-		WS_Release(ws, 0);
-		return (NULL);
+	WS_VSB_new(vsb, ws);
+	if (h != NULL)
+		VSB_cat(vsb, h);
+	for (i = 0; i < s->n; i++) {
+		if (s->p[i] != NULL && *s->p[i] != '\0')
+			VSB_cat(vsb, s->p[i]);
 	}
-	b = WS_Front(ws);
-	WS_Release(ws, r - b);
-	return (b);
+	return (WS_VSB_finish(vsb, ws));
 }
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishd/cache/cache_ws.c b/bin/varnishd/cache/cache_ws.c
index 2ea57116a..aad4db73a 100644
--- a/bin/varnishd/cache/cache_ws.c
+++ b/bin/varnishd/cache/cache_ws.c
@@ -342,3 +342,53 @@ WS_Overflowed(const struct ws *ws)
 		return (0);
 	return (1);
 }
+
+/*---------------------------------------------------------------------
+ * Build a VSB on a workspace.
+ * Usage pattern:
+ *
+ *	struct vsb vsb[1];
+ *	char *p;
+ *
+ *	WS_VSB_new(vsb, ctx->ws);
+ *	VSB_printf(vsb, "blablabla");
+ *	p = WS_VSB_finish(vsb);
+ *	if (p == NULL)
+ *		return (FAILURE);
+ */
+
+void
+WS_VSB_new(struct vsb *vsb, struct ws *ws)
+{
+	unsigned u;
+
+	WS_Assert(ws);
+	u = WS_ReserveAll(ws);
+	if (WS_Overflowed(ws) || u < 2) {
+		WS_MarkOverflow(ws);
+		/* Create a malloced-buffer VSB, and fail it up front */
+		AN(VSB_new(vsb, NULL, 2, 0));
+		VSB_cat(vsb, "XXX");
+	} else {
+		AN(VSB_new(vsb, WS_Front(ws), u, 0));
+	}
+}
+
+char *
+WS_VSB_finish(struct vsb *vsb, struct ws *ws)
+{
+	char *p;
+
+	WS_Assert(ws);
+	if (!VSB_finish(vsb)) {
+		p = VSB_data(vsb);
+		if (p == WS_Front(ws)) {
+			WS_Release(ws, VSB_len(vsb) + 1);
+			VSB_delete(vsb);
+			return (p);
+		}
+	}
+	VSB_delete(vsb);
+	WS_Release(ws, 0);
+	return (NULL);
+}


More information about the varnish-commit mailing list