Commit d9f31889 authored by Geoff Simmons's avatar Geoff Simmons

VMOD blob uses STRANDS instead of STRING_LIST.

parent bbc34e2d
......@@ -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) {
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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``.
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment