aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-11-28 09:50:14 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-11-28 09:50:14 +0100
commit7467e905e558228aab992f85406382518f2e1666 (patch)
treeab4b716757c36b66b80e3c2dac8ccecceea5fe8d
parent2cd37d65e221f7267e97360d21f55a2318b25355 (diff)
downloadbusybox-w32-7467e905e558228aab992f85406382518f2e1666.tar.gz
busybox-w32-7467e905e558228aab992f85406382518f2e1666.tar.bz2
busybox-w32-7467e905e558228aab992f85406382518f2e1666.zip
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>
-rw-r--r--libbb/uuencode.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 7c7f1cf1c..0e6fc8a3c 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -93,9 +93,10 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
93 char *dst = *pp_dst; 93 char *dst = *pp_dst;
94 unsigned ch = 0; 94 unsigned ch = 0;
95 int i = 0; 95 int i = 0;
96 int t;
96 97
97 while (*src) { 98 while ((t = (unsigned char)*src) != '\0') {
98 int t = (unsigned char)*src++; 99 src++;
99 100
100 /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */ 101 /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */
101 if (t >= '0' && t <= '9') 102 if (t >= '0' && t <= '9')
@@ -131,7 +132,7 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
131 } 132 }
132 } 133 }
133 *pp_dst = dst; 134 *pp_dst = dst;
134 /* i should be zero here if full 4-char block was decoded */ 135 /* i is zero here if full 4-char block was decoded */
135 return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ 136 return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
136} 137}
137 138
@@ -141,9 +142,10 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
141 char *dst = *pp_dst; 142 char *dst = *pp_dst;
142 uint64_t ch = 0; 143 uint64_t ch = 0;
143 int i = 0; 144 int i = 0;
145 int t;
144 146
145 while (*src) { 147 while ((t = (unsigned char)*src) != '\0') {
146 int t = (unsigned char)*src++; 148 src++;
147 149
148 /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ 150 /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
149 if (t >= '2' && t <= '7') 151 if (t >= '2' && t <= '7')
@@ -156,27 +158,35 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
156//TODO: add BASE64_FLAG_foo to die on bad char? 158//TODO: add BASE64_FLAG_foo to die on bad char?
157 continue; 159 continue;
158 160
159 ch = (ch << 5) | t; 161 ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */
160 if (++i == 8) { 162 if (++i == 8) {
163 /* testcase:
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 }
161 *dst++ = (char) (ch >> 32); 175 *dst++ = (char) (ch >> 32);
162 *dst++ = (char) (ch >> 24); 176 *dst++ = (char) (ch >> 24);
163 *dst++ = (char) (ch >> 16); 177 *dst++ = (char) (ch >> 16);
164 *dst++ = (char) (ch >> 8); 178 *dst++ = (char) (ch >> 8);
165 *dst++ = (char) ch; 179 *dst++ = (char) ch;
166 if (t == 0 && src[-1] == '=') { /* was last input char '='? */
167 const char *s = src;
168 while (*--s == '=' && --i != 0)
169 continue;
170 i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */
171 dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
172 i = 0;
173 break;
174 }
175 i = 0; 180 i = 0;
181 if (t < 0) /* was last input char '='? */
182 break;
176 } 183 }
177 } 184 }
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 */
178 *pp_dst = dst; 188 *pp_dst = dst;
179 /* i should be zero here if full 8-char block was decoded */ 189 /* i is zero here if full 8-char block was decoded */
180 return src - i; 190 return src - i;
181} 191}
182#endif 192#endif
@@ -193,19 +203,20 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
193#define uu_style_end (flags & BASE64_FLAG_UU_STOP) 203#define uu_style_end (flags & BASE64_FLAG_UU_STOP)
194#define base32 (flags & BASE64_32) 204#define base32 (flags & BASE64_32)
195 205
196 /* uuencoded files have 61 byte lines. Use 64 byte buffer 206 /* uuencoded files have 61 byte lines.
197 * to process line at a time. 207 * base32/64 have 76 byte lines by default.
208 * Use 80 byte buffer to process one line at a time.
198 */ 209 */
199 enum { BUFFER_SIZE = 64 }; 210 enum { BUFFER_SIZE = 80 };
200 211 /* decoded data is shorter than input, can use single buffer for both */
201 char in_buf[BUFFER_SIZE + 2]; 212 char buf[BUFFER_SIZE + 2];
202 char out_buf[BUFFER_SIZE / 4 * 3 + 2];
203 char *out_tail;
204 const char *in_tail;
205 int term_seen = 0; 213 int term_seen = 0;
206 int in_count = 0; 214 int in_count = 0;
207 215
208 while (1) { 216 while (1) {
217 char *out_tail;
218 const char *in_tail;
219
209 while (in_count < BUFFER_SIZE) { 220 while (in_count < BUFFER_SIZE) {
210 int ch = fgetc(src_stream); 221 int ch = fgetc(src_stream);
211 if (ch == exit_char) { 222 if (ch == exit_char) {
@@ -224,23 +235,23 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
224 */ 235 */
225 if (ch <= ' ') 236 if (ch <= ' ')
226 break; 237 break;
227 in_buf[in_count++] = ch; 238 buf[in_count++] = ch;
228 } 239 }
229 in_buf[in_count] = '\0'; 240 buf[in_count] = '\0';
230 241
231 /* Did we encounter "====" line? */ 242 /* Did we encounter "====" line? */
232 if (uu_style_end && strcmp(in_buf, "====") == 0) 243 if (uu_style_end && strcmp(buf, "====") == 0)
233 return; 244 return;
234 245
235 out_tail = out_buf; 246 out_tail = buf;
236#if ENABLE_BASE32 247#if ENABLE_BASE32
237 if (base32) 248 if (base32)
238 in_tail = decode_base32(&out_tail, in_buf); 249 in_tail = decode_base32(&out_tail, buf);
239 else 250 else
240#endif 251#endif
241 in_tail = decode_base64(&out_tail, in_buf); 252 in_tail = decode_base64(&out_tail, buf);
242 253
243 fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); 254 fwrite(buf, (out_tail - buf), 1, dst_stream);
244 255
245 if (term_seen) { 256 if (term_seen) {
246 /* Did we consume ALL characters? */ 257 /* Did we consume ALL characters? */
@@ -252,6 +263,6 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
252 263
253 /* It was partial decode */ 264 /* It was partial decode */
254 in_count = strlen(in_tail); 265 in_count = strlen(in_tail);
255 memmove(in_buf, in_tail, in_count); 266 memmove(buf, in_tail, in_count);
256 } 267 }
257} 268}