[Toybox] [CLEANUP] uuencode.c, pass 1, traditional encoding
Rob Landley
rob at landley.net
Thu Apr 11 21:43:42 PDT 2013
Now let's look at traditional encoding. (Same bat-file, same
bat-changeset. Oh _wow_ I'm dating myself with that reference, although
in my defense I only saw it in reruns.)
uu_3bytes() does the same "shift input into an int, output encoded 6
bit character" but the encoding is just add 32 to the value. (That's
the space character, and the next 63 characters after that are all
printable, so...) Just a really quick cleanup pass on this function:
remove curly brackets around single lines, and replace the assignment
into out[] with an xputc().
uu_line(): take out the special case to print something for a length 0
line (the standard doesn't require it). Instead wrap the whole thing in
if (len > 0) line the b64_line() does. The big xprintf() went away
because 3bytes is outputting stuff itself.
Traditional uuencoded lines start with the length of the line, so the
tuples are always 3 bytes encoded as 4 characters, and that initial
length tells you when to ignore bits of the end. That goes inside the
if() statement, along with a simple for() loop calling uu_3bytes() on
every 3 bytes of output until we're done. (We don't care about falling
off the end because we assume the input is big enough, and whatever
trailing garbage potentially winds up in those last couple bytes won't
get decoded at the far end due to the length saying not to.)
Hmmm, although now that I think about it this implies that encoding the
same file twice could produce slightly different results, even though
they decode to the same thing. But this would only actually happen if a
signal handler called us and crapped out the stack
non-deterministically, and modern linux actually has a separate signal
stack, so it can't actually happen. Otherwise buf[] contains either the
previous line or zero, deterministically. (That's black magic enough
I'm tempted to throw a memset() in there, but it's not worth the extra
code.)
Oh wait, we pass along len all the way to uu_3bytes() so it'll only
shift/load the bytes we give it into the integer output is produced
from, it's zero initialized and the rest remain zeroed. So nevermind,
already handled. :)
Where was I?
uuencode_uu() does the same inbuf/outbuf setup using toybuf, and again
the output buffer went away and we can replace both with a single input
buffer on the stack. The size of the xread was 45 bytes, and the spec
says:
> The maximum number of octets to be encoded on each line shall be 45.
So that's actually already correct. Adjust the whitespace (I tend to do
spaces after commas and statements that aren't function names like if
() vs func(), and around assignment characters. Habit I picked up
somewhere, more important to be consistent than right with whitespace.
I sometimes cheat and remove spaces to fit in 80 chars, but space after
commas is less important than space after if or before curly brackets...
Finally we get to uuencode_main():
The variable declarations got redone based on the needs of the code in
the function, so let's skip that except to note that I renamed
encode_filename to name because it was an unnecessarily long local
variable name. (A three line function needs less descriptive names than
a twenty line function. I try not to use a name like "k" if the scope
it lives in is longer than 10 lines or so, but I do note that "i" as a
loop index is tradithional! (Lightning strike! Yeah, discworld
reference.)
So: toybuf gets filled with a base64 table via a loop. (I could do that
only for -m but didn't bother, compared to the exec a for loop
initializing a 64-entry table with code that fits in a cache line is
trivial.)
The remaining cleanups are whitespace and changing the name of
encode_filename to just name.
And that's pass 1!
Rob
More information about the Toybox
mailing list