base32/64: code shrink
function old new delta decode_base64 180 178 -2 decode_base32 224 217 -7 read_base64 236 222 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-23) Total: -23 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
2cd37d65e2
commit
7467e905e5
@ -93,9 +93,10 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
|
||||
char *dst = *pp_dst;
|
||||
unsigned ch = 0;
|
||||
int i = 0;
|
||||
int t;
|
||||
|
||||
while (*src) {
|
||||
int t = (unsigned char)*src++;
|
||||
while ((t = (unsigned char)*src) != '\0') {
|
||||
src++;
|
||||
|
||||
/* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */
|
||||
if (t >= '0' && t <= '9')
|
||||
@ -131,7 +132,7 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
|
||||
}
|
||||
}
|
||||
*pp_dst = dst;
|
||||
/* i should be zero here if full 4-char block was decoded */
|
||||
/* i is zero here if full 4-char block was decoded */
|
||||
return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
|
||||
}
|
||||
|
||||
@ -141,9 +142,10 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
|
||||
char *dst = *pp_dst;
|
||||
uint64_t ch = 0;
|
||||
int i = 0;
|
||||
int t;
|
||||
|
||||
while (*src) {
|
||||
int t = (unsigned char)*src++;
|
||||
while ((t = (unsigned char)*src) != '\0') {
|
||||
src++;
|
||||
|
||||
/* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
|
||||
if (t >= '2' && t <= '7')
|
||||
@ -156,27 +158,35 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
|
||||
//TODO: add BASE64_FLAG_foo to die on bad char?
|
||||
continue;
|
||||
|
||||
ch = (ch << 5) | t;
|
||||
ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */
|
||||
if (++i == 8) {
|
||||
/* testcase:
|
||||
* echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
|
||||
* IOW, decoding of
|
||||
* EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
|
||||
* ====
|
||||
* should correctly stitch together the tail.
|
||||
*/
|
||||
if (t == 0) {
|
||||
const char *s = src;
|
||||
while (*--s == '=')
|
||||
t--;
|
||||
}
|
||||
*dst++ = (char) (ch >> 32);
|
||||
*dst++ = (char) (ch >> 24);
|
||||
*dst++ = (char) (ch >> 16);
|
||||
*dst++ = (char) (ch >> 8);
|
||||
*dst++ = (char) ch;
|
||||
if (t == 0 && src[-1] == '=') { /* was last input char '='? */
|
||||
const char *s = src;
|
||||
while (*--s == '=' && --i != 0)
|
||||
continue;
|
||||
i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */
|
||||
dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
i = 0;
|
||||
if (t < 0) /* was last input char '='? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t < 0) /* was last input char '='? */
|
||||
/* -t is the count of =, must be 1, 3, 4 or 6 */
|
||||
dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
|
||||
*pp_dst = dst;
|
||||
/* i should be zero here if full 8-char block was decoded */
|
||||
/* i is zero here if full 8-char block was decoded */
|
||||
return src - i;
|
||||
}
|
||||
#endif
|
||||
@ -193,19 +203,20 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
|
||||
#define uu_style_end (flags & BASE64_FLAG_UU_STOP)
|
||||
#define base32 (flags & BASE64_32)
|
||||
|
||||
/* uuencoded files have 61 byte lines. Use 64 byte buffer
|
||||
* to process line at a time.
|
||||
/* uuencoded files have 61 byte lines.
|
||||
* base32/64 have 76 byte lines by default.
|
||||
* Use 80 byte buffer to process one line at a time.
|
||||
*/
|
||||
enum { BUFFER_SIZE = 64 };
|
||||
|
||||
char in_buf[BUFFER_SIZE + 2];
|
||||
char out_buf[BUFFER_SIZE / 4 * 3 + 2];
|
||||
char *out_tail;
|
||||
const char *in_tail;
|
||||
enum { BUFFER_SIZE = 80 };
|
||||
/* decoded data is shorter than input, can use single buffer for both */
|
||||
char buf[BUFFER_SIZE + 2];
|
||||
int term_seen = 0;
|
||||
int in_count = 0;
|
||||
|
||||
while (1) {
|
||||
char *out_tail;
|
||||
const char *in_tail;
|
||||
|
||||
while (in_count < BUFFER_SIZE) {
|
||||
int ch = fgetc(src_stream);
|
||||
if (ch == exit_char) {
|
||||
@ -224,23 +235,23 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
|
||||
*/
|
||||
if (ch <= ' ')
|
||||
break;
|
||||
in_buf[in_count++] = ch;
|
||||
buf[in_count++] = ch;
|
||||
}
|
||||
in_buf[in_count] = '\0';
|
||||
buf[in_count] = '\0';
|
||||
|
||||
/* Did we encounter "====" line? */
|
||||
if (uu_style_end && strcmp(in_buf, "====") == 0)
|
||||
if (uu_style_end && strcmp(buf, "====") == 0)
|
||||
return;
|
||||
|
||||
out_tail = out_buf;
|
||||
out_tail = buf;
|
||||
#if ENABLE_BASE32
|
||||
if (base32)
|
||||
in_tail = decode_base32(&out_tail, in_buf);
|
||||
in_tail = decode_base32(&out_tail, buf);
|
||||
else
|
||||
#endif
|
||||
in_tail = decode_base64(&out_tail, in_buf);
|
||||
in_tail = decode_base64(&out_tail, buf);
|
||||
|
||||
fwrite(out_buf, (out_tail - out_buf), 1, dst_stream);
|
||||
fwrite(buf, (out_tail - buf), 1, dst_stream);
|
||||
|
||||
if (term_seen) {
|
||||
/* Did we consume ALL characters? */
|
||||
@ -252,6 +263,6 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
|
||||
|
||||
/* It was partial decode */
|
||||
in_count = strlen(in_tail);
|
||||
memmove(in_buf, in_tail, in_count);
|
||||
memmove(buf, in_tail, in_count);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user