[git commit] base32/64: code shrink

Denys Vlasenko vda.linux at googlemail.com
Sat Nov 28 11:33:50 UTC 2020


commit: https://git.busybox.net/busybox/commit/?id=f140b49f5f631b09acf7811933d843fe17f06343
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
decode_base64                                        178     173      -5
decode_base32                                        217     186     -31
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-36)             Total: -36 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/uuencode.c | 66 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 0e6fc8a3c..6205af261 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -92,8 +92,8 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
 	unsigned ch = 0;
+	unsigned t;
 	int i = 0;
-	int t;
 
 	while ((t = (unsigned char)*src) != '\0') {
 		src++;
@@ -117,11 +117,11 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 			continue;
 
 		ch = (ch << 6) | t;
-		if (++i == 4) {
+		i = (i + 1) & 3;
+		if (i == 0) {
 			*dst++ = (char) (ch >> 16);
 			*dst++ = (char) (ch >> 8);
 			*dst++ = (char) ch;
-			i = 0;
 			if (ch & 0x1000000) { /* was last input char '='? */
 				dst--;
 				if (ch & (0x1000000 << 6)) /* was it "=="? */
@@ -140,9 +140,9 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
-	uint64_t ch = 0;
+	int64_t ch = 0;
+	unsigned t;
 	int i = 0;
-	int t;
 
 	while ((t = (unsigned char)*src) != '\0') {
 		src++;
@@ -150,44 +150,52 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 		/* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
 		if (t >= '2' && t <= '7')
 			t = t - '2' + 26;
-		else if ((t|0x20) >= 'a' && (t|0x20) <= 'z')
-			t = (t|0x20) - 'a';
 		else if (t == '=' && i > 1)
 			t = 0;
-		else
+		else {
+			t = (t | 0x20) - 'a';
+			if (t > 25)
 //TODO: add BASE64_FLAG_foo to die on bad char?
-			continue;
+				continue;
+		}
 
-		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--;
-			}
+		ch = (ch << 5) | t;
+		i = (i + 1) & 7;
+		if (i == 0) {
 			*dst++ = (char) (ch >> 32);
+			if (src[-1] == '=') /* was last input char '='? */
+				goto tail;
 			*dst++ = (char) (ch >> 24);
 			*dst++ = (char) (ch >> 16);
 			*dst++ = (char) (ch >> 8);
 			*dst++ = (char) ch;
-			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 is zero here if full 8-char block was decoded */
 	return src - i;
+ tail:
+	{
+		const char *s = src;
+		while (*--s == '=')
+			i++;
+		/* Why duplicate the below code? 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==
+		 * ====
+		 * must correctly stitch together the tail, must not overwrite
+		 * the tail before it is analyzed! (we can be decoding in-place)
+		 * Else testcase fails, prints trailing extra NUL bytes.
+		 */
+		*dst++ = (char) (ch >> 24);
+		*dst++ = (char) (ch >> 16);
+		*dst++ = (char) (ch >> 8);
+		*dst++ = (char) ch;
+		dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
+	}
+	*pp_dst = dst;
+	return src;
 }
 #endif
 


More information about the busybox-cvs mailing list