Commit 2f09cd05 authored by Geoff Simmons's avatar Geoff Simmons

tweak base64_encode() a bit

parent 0811954b
......@@ -52,17 +52,6 @@ decode(char *restrict *restrict dest, char *restrict const buf,
return 1;
}
/*
* Base64-encode *in (size: inlen) into the blob supplied as rblob. If
* there is insufficient space, it will bail out and return
* NULL. Otherwise, it will null-terminate and return the blob.
* The enc argument specifies the alphabet and whether padding is used.
* Inspired heavily by gnulib/Simon Josefsson (as referenced in RFC4648)
*
* XXX: tmp[] and idx are used to ensure the reader (and author) retains
* XXX: a limited amount of sanity. They are strictly speaking not
* XXX: necessary, if you don't mind going crazy.
*/
ssize_t
base64_encode(const enum encoding enc, char *restrict const buf,
const size_t maxlen, const char *restrict const inbuf,
......@@ -71,68 +60,46 @@ base64_encode(const enum encoding enc, char *restrict const buf,
const struct b64_alphabet *alpha = &b64_alphabet[enc];
char *p = buf;
const char *in = inbuf;
size_t outlen = maxlen, inlen = inlength;
unsigned char tmp[3], idx;
AN(buf);
AN(alpha);
if (in == NULL || inlen == 0)
if (in == NULL || inlength == 0)
return 0;
if ((enc != BASE64URLNOPAD && outlen < base64_encode_l(inlen))
|| outlen < base64nopad_encode_l(inlen))
if ((enc != BASE64URLNOPAD && maxlen < base64_encode_l(inlength))
|| maxlen < base64nopad_encode_l(inlength))
return -1;
while (1) {
assert(inlen);
assert(outlen > 3);
while (in < inbuf + inlength) {
unsigned char *tmp, idx;
size_t rest = (inbuf + inlength) - in;
tmp[0] = (unsigned char) in[0];
tmp[1] = (unsigned char) in[1];
tmp[2] = (unsigned char) in[2];
tmp = (unsigned char *) in;
*p++ = alpha->b64[(tmp[0] >> 2) & 0x3f];
idx = (tmp[0] << 4);
if (inlen > 1)
if (rest > 1)
idx += (tmp[1] >> 4);
idx &= 0x3f;
*p++ = alpha->b64[idx];
*p++ = alpha->b64[idx & 0x3f];
if (inlen > 1) {
if (rest > 1) {
idx = (tmp[1] << 2);
if (inlen > 2)
if (rest > 2)
idx += tmp[2] >> 6;
idx &= 0x3f;
*p++ = alpha->b64[idx];
} else {
if (alpha->padding)
*p++ = alpha->padding;
*p++ = alpha->b64[idx & 0x3f];
}
else if (alpha->padding)
*p++ = alpha->padding;
if (inlen > 2) {
if (rest > 2)
*p++ = alpha->b64[tmp[2] & 0x3f];
} else {
if (alpha->padding)
*p++ = alpha->padding;
}
/*
* XXX: Only consume 4 bytes, but since we need a fifth for
* XXX: NULL later on, we might as well test here.
*/
assert(outlen >= 5);
outlen -= 4;
if (inlen < 4)
break;
else if (alpha->padding)
*p++ = alpha->padding;
inlen -= 3;
in += 3;
}
assert(outlen > 0);
assert(p >= buf && p - buf <= maxlen);
return p - buf;
}
......
......@@ -32,7 +32,7 @@
#define PAD -2
static const struct b64_alphabet {
const char *b64;
const char b64[64];
const int8_t i64[256];
const int padding;
} b64_alphabet[] = {
......@@ -46,7 +46,7 @@ static const struct b64_alphabet {
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, 62, ILL, ILL, ILL, 63, /* +, - */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 -7 */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 - 7 */
60, 61, ILL, ILL, ILL, PAD, ILL, ILL, /* 8, 9, = */
ILL, 0, 1, 2, 3, 4, 5, 6, /* A - G */
7, 8, 9, 10, 11, 12, 13, 14, /* H - O */
......@@ -85,7 +85,7 @@ static const struct b64_alphabet {
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, ILL, ILL, 62, ILL, ILL, /* - */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 -7 */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 - 7 */
60, 61, ILL, ILL, ILL, PAD, ILL, ILL, /* 8, 9, = */
ILL, 0, 1, 2, 3, 4, 5, 6, /* A - G */
7, 8, 9, 10, 11, 12, 13, 14, /* H - O */
......@@ -124,7 +124,7 @@ static const struct b64_alphabet {
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
ILL, ILL, ILL, ILL, ILL, 62, ILL, ILL, /* - */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 -7 */
52, 53, 54, 55, 56, 57, 58, 59, /* 0 - 7 */
60, 61, ILL, ILL, ILL, ILL, ILL, ILL, /* 8, 9 */
ILL, 0, 1, 2, 3, 4, 5, 6, /* A - G */
7, 8, 9, 10, 11, 12, 13, 14, /* H - O */
......
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