Commit 9c8a963f authored by Nils Goroll's avatar Nils Goroll

use a call table for encode/decode functions

This removes some switch/case clutter at a slight potential cost for
the additional indirection.
parent 7f1e9a1e
......@@ -34,6 +34,26 @@
#include "vrt.h"
#include "vas.h"
#define base64_l(l) (((l) << 2) / 3)
size_t
base64nopad_encode_l(size_t l)
{
return base64_l(l) + 4;
}
size_t
base64_encode_l(size_t l)
{
return (((base64_l(l)) + 3) & ~3) + 1;
}
size_t
base64_decode_l(size_t l)
{
return ((l) * 3) >> 2;
}
static inline int
decode(char *restrict *restrict dest, char *restrict const buf,
const size_t maxlen, unsigned u, const int n)
......
......@@ -35,6 +35,18 @@
#include "vrt.h"
#include "vas.h"
size_t
hex_encode_l(size_t l)
{
return ((l) << 1) + 1;
}
size_t
hex_decode_l(size_t l)
{
return ((l) + 1) >> 1;
}
static const char hex_alphabet[][16] = {
"0123456789abcdef",
"0123456789ABCDEF"
......
......@@ -34,6 +34,18 @@
#include "vrt.h"
#include "vas.h"
size_t
id_encode_l(size_t l)
{
return l + 1;
}
size_t
id_decode_l(size_t l)
{
return l;
}
ssize_t
id_encode(const enum encoding enc, char *restrict const buf,
const size_t maxlen, const char *restrict const in,
......
......@@ -46,6 +46,62 @@ struct vmod_blobcode_blob {
pthread_mutex_t lock;
};
#define B64_FUNCS \
.decode_l = base64_decode_l, \
.decode = base64_decode, \
.encode = base64_encode
#define HEX_FUNCS \
.decode_l = hex_decode_l, \
.decode = hex_decode, \
.encode_l = hex_encode_l, \
.encode = hex_encode
static const struct vmod_blobcode_fptr {
len_f *decode_l;
decode_f *decode;
len_f *encode_l;
encode_f *encode;
} func[__MAX_ENCODING] = {
[_INVALID] = {
/* make implicit null init explicit for clarity */
.decode_l = NULL,
.decode = NULL,
.encode_l = NULL,
.encode = NULL
},
[IDENTITY] = {
.decode_l = id_decode_l,
.decode = id_decode,
.encode_l = id_encode_l,
.encode = id_encode
},
[BASE64] = {
B64_FUNCS,
.encode_l = base64_encode_l
},
[BASE64URL] = {
B64_FUNCS,
.encode_l = base64_encode_l
},
[BASE64URLNOPAD] = {
B64_FUNCS,
.encode_l = base64nopad_encode_l
},
[HEX] = {
HEX_FUNCS
},
[HEXUC] = {
HEX_FUNCS
},
[HEXLC] = {
HEX_FUNCS
}
};
#undef B64_FUNCS
#undef HEX_FUNCS
#define ERR(ctx, msg) \
errmsg((ctx), "vmod blobcode error: " msg)
......@@ -91,56 +147,8 @@ decode_l_va(enum encoding dec, const char * const p, va_list ap)
if (next != NULL)
len += strlen(next);
switch(dec) {
case IDENTITY:
return len;
case BASE64:
case BASE64URL:
case BASE64URLNOPAD:
return base64_decode_l(len);
case HEX:
return hex_decode_l(len);
default:
WRONG("Illegal decoding");
}
}
static inline ssize_t __match_proto__(decode_f)
decode(const enum encoding dec, char *restrict const buf,
const size_t maxlen, const char *restrict const p, va_list ap)
{
errno = 0;
switch(dec) {
case IDENTITY:
return id_decode(dec, buf, maxlen, p, ap);
case BASE64:
case BASE64URL:
case BASE64URLNOPAD:
return base64_decode(dec, buf, maxlen, p, ap);
case HEX:
return hex_decode(dec, buf, maxlen, p, ap);
default:
WRONG("Illegal decoding");
}
}
static inline ssize_t __match_proto__(encode_f)
encode(const enum encoding enc, char *restrict const buf, const size_t maxlen,
const char *restrict const in, const size_t inlen)
{
switch(enc) {
case IDENTITY:
return id_encode(enc, buf, maxlen, in, inlen);
case BASE64:
case BASE64URL:
case BASE64URLNOPAD:
return base64_encode(enc, buf, maxlen, in, inlen);
case HEXUC:
case HEXLC:
return hex_encode(enc, buf, maxlen, in, inlen);
default:
WRONG("Illegal encoding");
}
AENC(dec);
return(func[dec].decode_l(len));
}
static void
......@@ -192,6 +200,8 @@ vmod_blob__init(VRT_CTX, struct vmod_blobcode_blob **blobp, const char *vcl_name
AN(blobp);
AZ(*blobp);
AN(vcl_name);
AENC(dec);
ALLOC_OBJ(b, VMOD_BLOBCODE_BLOB_MAGIC);
AN(b);
*blobp = b;
......@@ -215,7 +225,7 @@ vmod_blob__init(VRT_CTX, struct vmod_blobcode_blob **blobp, const char *vcl_name
}
va_start(ap, p);
len = decode(dec, b->blob.priv, len, p, ap);
len = func[dec].decode(dec, b->blob.priv, len, p, ap);
va_end(ap);
if (len == -1) {
......@@ -248,6 +258,7 @@ VCL_STRING
vmod_blob_encode(VRT_CTX, struct vmod_blobcode_blob *b, VCL_ENUM encs)
{
enum encoding enc = parse_encoding(encs);
AENC(enc);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(b, VMOD_BLOBCODE_BLOB_MAGIC);
......@@ -258,26 +269,8 @@ vmod_blob_encode(VRT_CTX, struct vmod_blobcode_blob *b, VCL_ENUM encs)
if (b->encoding[enc] == NULL) {
AZ(pthread_mutex_lock(&b->lock));
if (b->encoding[enc] == NULL) {
ssize_t len;
switch(enc) {
case IDENTITY:
len = b->blob.len + 1;
break;
case HEXUC:
case HEXLC:
len = hex_encode_l(b->blob.len);
break;
case BASE64:
case BASE64URL:
len = base64_encode_l(b->blob.len);
break;
case BASE64URLNOPAD:
len = base64nopad_encode_l(b->blob.len);
break;
default:
WRONG("Illegal encoding");
}
ssize_t len = func[enc].encode_l(b->blob.len);
assert(len >= 0);
if (len == 0)
b->encoding[enc] = "";
......@@ -287,8 +280,11 @@ vmod_blob_encode(VRT_CTX, struct vmod_blobcode_blob *b, VCL_ENUM encs)
ERRNOMEM(ctx, "cannot encode");
else {
const char *s = b->encoding[enc];
len = encode(enc, (void *) s, len,
b->blob.priv, b->blob.len);
len =
func[enc].encode(
enc, (void *) s, len,
b->blob.priv,
b->blob.len);
assert(len >= 0);
if (len == 0) {
free((void *) s);
......@@ -338,6 +334,8 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
ssize_t len;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AENC(dec);
if (INIT_FINI(ctx)) {
ILLEGAL(ctx, "decode()");
return NULL;
......@@ -357,7 +355,7 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
buf = wb_buf(&wb);
va_start(ap, p);
len = decode(dec, buf, wb_space(&wb), p, ap);
len = func[dec].decode(dec, buf, wb_space(&wb), p, ap);
va_end(ap);
if (len == -1) {
......@@ -386,6 +384,8 @@ vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
ssize_t len;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AENC(enc);
if (INIT_FINI(ctx)) {
ILLEGAL(ctx, "encode()");
return NULL;
......@@ -399,7 +399,8 @@ vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
return NULL;
}
len = encode(enc, wb_buf(&wb), wb_space(&wb), b->priv, b->len);
len = func[enc].encode(enc,
wb_buf(&wb), wb_space(&wb), b->priv, b->len);
if (len == -1) {
ERRNOMEM(ctx, "cannot encode");
......@@ -429,6 +430,9 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
}
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
AENC(dec);
AENC(enc);
/* Allocate space for the decoded blob on the stack */
va_start(ap, p);
size_t l = decode_l_va(dec, p, ap);
......@@ -439,7 +443,7 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
char buf[l];
va_start(ap, p);
len = decode(dec, buf, l, p, ap);
len = func[dec].decode(dec, buf, l, p, ap);
va_end(ap);
if (len == -1) {
......@@ -463,7 +467,7 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
return NULL;
}
len = encode(enc, wb_buf(&wb), wb_space(&wb), buf, len);
len = func[enc].encode(enc, wb_buf(&wb), wb_space(&wb), buf, len);
if (len == -1) {
ERRNOMEM(ctx, "cannot encode after decode");
wb_reset(&wb);
......
......@@ -32,16 +32,13 @@
#include "parse_encoding.h"
#define AENC(enc) assert((enc) > _INVALID && (enc) < __MAX_ENCODING)
/*
* SAFE LENGTH ESTIMATES
* Length estimate interface
*/
#define base64_decode_l(l) (((l) * 3) >> 2)
#define base64_l(l) (((l) << 2) / 3)
#define base64nopad_encode_l(l) (base64_l(l) + 4)
#define base64_encode_l(l) ((((base64_l(l)) + 3) & ~3) + 1)
#define hex_encode_l(l) (((l) << 1) + 1)
#define hex_decode_l(l) (((l) + 1) >> 1)
typedef
size_t len_f(size_t);
/*
* General interface for an encoder: encode the data at in of length inlen
......@@ -99,13 +96,23 @@ ssize_t decode_f(const enum encoding dec, char *restrict const buf,
const size_t maxlen, const char *restrict const p, va_list ap);
/* id.c */
len_f id_encode_l;
len_f id_decode_l;
encode_f id_encode;
decode_f id_decode;
/* base64.c */
len_f base64_decode_l;
len_f base64nopad_encode_l;
len_f base64_encode_l;
encode_f base64_encode;
decode_f base64_decode;
/* hex.c */
len_f hex_encode_l;
len_f hex_decode_l;
encode_f hex_encode;
decode_f hex_decode;
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