aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-11-28 12:33:50 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-11-28 12:33:50 +0100
commitf140b49f5f631b09acf7811933d843fe17f06343 (patch)
tree97d5e77ed73a3864bd8ea4ca7b9ad0af8130e89a
parent7467e905e558228aab992f85406382518f2e1666 (diff)
downloadbusybox-w32-f140b49f5f631b09acf7811933d843fe17f06343.tar.gz
busybox-w32-f140b49f5f631b09acf7811933d843fe17f06343.tar.bz2
busybox-w32-f140b49f5f631b09acf7811933d843fe17f06343.zip
base32/64: code shrink
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@googlemail.com>
-rw-r--r--libbb/uuencode.c66
1 files 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)
92{ 92{
93 char *dst = *pp_dst; 93 char *dst = *pp_dst;
94 unsigned ch = 0; 94 unsigned ch = 0;
95 unsigned t;
95 int i = 0; 96 int i = 0;
96 int t;
97 97
98 while ((t = (unsigned char)*src) != '\0') { 98 while ((t = (unsigned char)*src) != '\0') {
99 src++; 99 src++;
@@ -117,11 +117,11 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
117 continue; 117 continue;
118 118
119 ch = (ch << 6) | t; 119 ch = (ch << 6) | t;
120 if (++i == 4) { 120 i = (i + 1) & 3;
121 if (i == 0) {
121 *dst++ = (char) (ch >> 16); 122 *dst++ = (char) (ch >> 16);
122 *dst++ = (char) (ch >> 8); 123 *dst++ = (char) (ch >> 8);
123 *dst++ = (char) ch; 124 *dst++ = (char) ch;
124 i = 0;
125 if (ch & 0x1000000) { /* was last input char '='? */ 125 if (ch & 0x1000000) { /* was last input char '='? */
126 dst--; 126 dst--;
127 if (ch & (0x1000000 << 6)) /* was it "=="? */ 127 if (ch & (0x1000000 << 6)) /* was it "=="? */
@@ -140,9 +140,9 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
140const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) 140const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
141{ 141{
142 char *dst = *pp_dst; 142 char *dst = *pp_dst;
143 uint64_t ch = 0; 143 int64_t ch = 0;
144 unsigned t;
144 int i = 0; 145 int i = 0;
145 int t;
146 146
147 while ((t = (unsigned char)*src) != '\0') { 147 while ((t = (unsigned char)*src) != '\0') {
148 src++; 148 src++;
@@ -150,44 +150,52 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
150 /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ 150 /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
151 if (t >= '2' && t <= '7') 151 if (t >= '2' && t <= '7')
152 t = t - '2' + 26; 152 t = t - '2' + 26;
153 else if ((t|0x20) >= 'a' && (t|0x20) <= 'z')
154 t = (t|0x20) - 'a';
155 else if (t == '=' && i > 1) 153 else if (t == '=' && i > 1)
156 t = 0; 154 t = 0;
157 else 155 else {
156 t = (t | 0x20) - 'a';
157 if (t > 25)
158//TODO: add BASE64_FLAG_foo to die on bad char? 158//TODO: add BASE64_FLAG_foo to die on bad char?
159 continue; 159 continue;
160 }
160 161
161 ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */ 162 ch = (ch << 5) | t;
162 if (++i == 8) { 163 i = (i + 1) & 7;
163 /* testcase: 164 if (i == 0) {
164 * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
165 * IOW, decoding of
166 * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
167 * ====
168 * should correctly stitch together the tail.
169 */
170 if (t == 0) {
171 const char *s = src;
172 while (*--s == '=')
173 t--;
174 }
175 *dst++ = (char) (ch >> 32); 165 *dst++ = (char) (ch >> 32);
166 if (src[-1] == '=') /* was last input char '='? */
167 goto tail;
176 *dst++ = (char) (ch >> 24); 168 *dst++ = (char) (ch >> 24);
177 *dst++ = (char) (ch >> 16); 169 *dst++ = (char) (ch >> 16);
178 *dst++ = (char) (ch >> 8); 170 *dst++ = (char) (ch >> 8);
179 *dst++ = (char) ch; 171 *dst++ = (char) ch;
180 i = 0;
181 if (t < 0) /* was last input char '='? */
182 break;
183 } 172 }
184 } 173 }
185 if (t < 0) /* was last input char '='? */
186 /* -t is the count of =, must be 1, 3, 4 or 6 */
187 dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
188 *pp_dst = dst; 174 *pp_dst = dst;
189 /* i is zero here if full 8-char block was decoded */ 175 /* i is zero here if full 8-char block was decoded */
190 return src - i; 176 return src - i;
177 tail:
178 {
179 const char *s = src;
180 while (*--s == '=')
181 i++;
182 /* Why duplicate the below code? Testcase:
183 * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
184 * IOW, decoding of
185 * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
186 * ====
187 * must correctly stitch together the tail, must not overwrite
188 * the tail before it is analyzed! (we can be decoding in-place)
189 * Else testcase fails, prints trailing extra NUL bytes.
190 */
191 *dst++ = (char) (ch >> 24);
192 *dst++ = (char) (ch >> 16);
193 *dst++ = (char) (ch >> 8);
194 *dst++ = (char) ch;
195 dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
196 }
197 *pp_dst = dst;
198 return src;
191} 199}
192#endif 200#endif
193 201