diff --git a/ChangeLog b/ChangeLog index 7859c142ffd2ae5f697c5808e80e197a96edf1fd..9ee8aeae11d1221898b40dcb3fff4cafbdbbd306 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2015-02-10 Niels Möller <nisse@lysator.liu.se> + + Base-64 generalization, contributed by Amos Jeffries. + * base64.h (struct base64_encode_ctx): Added pointer to alphabet. + (struct base64_decode_ctx): Added pointer to decoding table. + * base64-decode.c (base64_decode_init): Initialize table pointer. + Moved definition of table to local scope. + (base64_decode_single): Use the context's decoding table. + * base64-encode.c (ENCODE): Added alphabet argument. Updated all + uses. + (encode_raw): New static function, like base64_encode_raw + but with an alphabet argument. + (base64_encode_raw): Call encode_raw. + (base64_encode_init): Initialize alphabet pointer. + (base64_encode_single, base64_encode_update, base64_encode_final): + Use the context's alphabet. + 2015-02-09 Niels Möller <nisse@lysator.liu.se> * base64-encode.c (base64_encode): Deleted old #if:ed out diff --git a/base64-decode.c b/base64-decode.c index f622baac88a0c9d139ca55b3aa1ec469495e1621..337ea3953d6ab6d2f0f1c30f635f5609d90e63c1 100644 --- a/base64-decode.c +++ b/base64-decode.c @@ -42,32 +42,32 @@ #define TABLE_SPACE -2 #define TABLE_END -3 -static const signed char -decode_table[0x100] = -{ - /* White space is HT, VT, FF, CR, LF and SPC */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -}; - void base64_decode_init(struct base64_decode_ctx *ctx) { + static const signed char base64_decode_table[0x100] = + { + /* White space is HT, VT, FF, CR, LF and SPC */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + ctx->word = ctx->bits = ctx->padding = 0; + ctx->table = base64_decode_table; } int @@ -75,9 +75,7 @@ base64_decode_single(struct base64_decode_ctx *ctx, uint8_t *dst, uint8_t src) { - int data; - - data = decode_table[src]; + int data = ctx->table[src]; switch(data) { diff --git a/base64-encode.c b/base64-encode.c index b0b921f605e8a3bf3ef3d3490286bd1375e0b11d..0e81b3f5e1abe3bd682e2751ce1170891c174910 100644 --- a/base64-encode.c +++ b/base64-encode.c @@ -38,15 +38,11 @@ #include "base64.h" -static const uint8_t encode_table[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -#define ENCODE(x) (encode_table[0x3F & (x)]) +#define ENCODE(alphabet,x) ((alphabet)[0x3F & (x)]) -void -base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src) +static void +encode_raw(const char *alphabet, + uint8_t *dst, size_t length, const uint8_t *src) { const uint8_t *in = src + length; uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length); @@ -61,45 +57,57 @@ base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src) { case 1: *--out = '='; - *--out = ENCODE(in[0] << 4); + *--out = ENCODE(alphabet, (in[0] << 4)); break; case 2: - *--out = ENCODE( in[1] << 2); - *--out = ENCODE((in[0] << 4) | (in[1] >> 4)); + *--out = ENCODE(alphabet, (in[1] << 2)); + *--out = ENCODE(alphabet, ((in[0] << 4) | (in[1] >> 4))); break; default: abort(); } - *--out = ENCODE(in[0] >> 2); + *--out = ENCODE(alphabet, (in[0] >> 2)); } while (in > src) { in -= 3; - *--out = ENCODE( in[2]); - *--out = ENCODE((in[1] << 2) | (in[2] >> 6)); - *--out = ENCODE((in[0] << 4) | (in[1] >> 4)); - *--out = ENCODE( in[0] >> 2); + *--out = ENCODE(alphabet, (in[2])); + *--out = ENCODE(alphabet, ((in[1] << 2) | (in[2] >> 6))); + *--out = ENCODE(alphabet, ((in[0] << 4) | (in[1] >> 4))); + *--out = ENCODE(alphabet, (in[0] >> 2)); } assert(in == src); assert(out == dst); } +static const uint8_t base64_encode_table[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +void +base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src) +{ + encode_raw(base64_encode_table, dst, length, src); +} + void base64_encode_group(uint8_t *dst, uint32_t group) { - *dst++ = ENCODE(group >> 18); - *dst++ = ENCODE(group >> 12); - *dst++ = ENCODE(group >> 6); - *dst++ = ENCODE(group); + *dst++ = ENCODE(base64_encode_table, (group >> 18)); + *dst++ = ENCODE(base64_encode_table, (group >> 12)); + *dst++ = ENCODE(base64_encode_table, (group >> 6)); + *dst++ = ENCODE(base64_encode_table, group); } void base64_encode_init(struct base64_encode_ctx *ctx) { ctx->word = ctx->bits = 0; + ctx->alphabet = base64_encode_table; } /* Encodes a single byte. */ @@ -115,7 +123,7 @@ base64_encode_single(struct base64_encode_ctx *ctx, while (bits >= 6) { bits -= 6; - dst[done++] = ENCODE(word >> bits); + dst[done++] = ENCODE(ctx->alphabet, (word >> bits)); } ctx->bits = bits; @@ -152,7 +160,7 @@ base64_encode_update(struct base64_encode_ctx *ctx, { assert(!(bulk % 3)); - base64_encode_raw(dst + done, bulk, src); + encode_raw(ctx->alphabet, dst + done, bulk, src); done += BASE64_ENCODE_RAW_LENGTH(bulk); src += bulk; left = left_over; @@ -180,7 +188,7 @@ base64_encode_final(struct base64_encode_ctx *ctx, if (bits) { - dst[done++] = ENCODE(ctx->word << (6 - ctx->bits)); + dst[done++] = ENCODE(ctx->alphabet, (ctx->word << (6 - ctx->bits))); for (; bits < 6; bits += 2) dst[done++] = '='; diff --git a/base64.h b/base64.h index a6fb8235c6eada43b32c1396b441e94dc9b3c9d4..07a8e2b716f45c36ddb8c815f5057cffe652e4e0 100644 --- a/base64.h +++ b/base64.h @@ -73,8 +73,10 @@ struct base64_encode_ctx { unsigned word; /* Leftover bits */ unsigned bits; /* Number of bits, always 0, 2, or 4. */ + const uint8_t *alphabet; /* Alphabet to use for encoding */ }; +/* Initialize encoding context for base-64 */ void base64_encode_init(struct base64_encode_ctx *ctx); @@ -123,8 +125,10 @@ struct base64_decode_ctx /* Number of padding characters encountered */ unsigned padding; + const signed char *table; /* Decoding table */ }; +/* Initialize decoding context for base-64 */ void base64_decode_init(struct base64_decode_ctx *ctx);