blob: 25e37d416be23a106a1266c8fe3172f4a84c4fe3 [file] [log] [blame]
/* base64.c - Encode and decode base64
*
* Copyright 2014 Rob Landley <rob@landley.net>
*
* No standard
USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
config BASE64
bool "base64"
default y
help
usage: base64 [-di] [-w COLUMNS] [FILE...]
Encode or decode in base64.
-d Decode
-i Ignore non-alphabetic characters
-w Wrap output at COLUMNS (default 76 or 0 for no wrap)
config BASE32
bool "base32"
default y
help
usage: base32 [-di] [-w COLUMNS] [FILE...]
Encode or decode in base32.
-d Decode
-i Ignore non-alphabetic characters
-w Wrap output at COLUMNS (default 76 or 0 for no wrap)
*/
#define FOR_base64
#include "toys.h"
GLOBALS(
long w;
unsigned total;
unsigned n; // number of bits used in encoding. 5 for base32, 6 for base64
unsigned align; // number of bits to align to
)
static void wraputchar(int c, int *x)
{
putchar(c);
TT.total++;
if (TT.w && ++*x == TT.w) {
*x = 0;
xputc('\n');
};
}
static void do_base_n(int fd, char *name)
{
int out = 0, bits = 0, x = 0, i, len;
char *buf = toybuf+128;
TT.total = 0;
for (;;) {
// If no more data, flush buffer
if (!(len = xread(fd, buf, sizeof(toybuf)-128))) {
if (!FLAG(d)) {
if (bits) wraputchar(toybuf[out<<(TT.n-bits)], &x);
while (TT.total&TT.align) wraputchar('=', &x);
if (x) xputc('\n');
}
return;
}
for (i=0; i<len; i++) {
if (FLAG(d)) {
if (buf[i] == '=') return;
if ((x = stridx(toybuf, buf[i])) != -1) {
out = (out<<TT.n) + x;
bits += TT.n;
if (bits >= 8) {
putchar(out >> (bits -= 8));
out &= (1<<bits)-1;
if (ferror(stdout)) perror_exit(0);
}
continue;
}
if (buf[i] == '\n' || FLAG(i)) continue;
break;
} else {
out = (out<<8) + buf[i];
bits += 8;
while (bits >= TT.n) {
wraputchar(toybuf[out >> (bits -= TT.n)], &x);
out &= (1<<bits)-1;
}
}
}
}
}
void base64_main(void)
{
TT.n = 6;
TT.align = 3;
base64_init(toybuf);
loopfiles(toys.optargs, do_base_n);
}
#define CLEANUP_base64
#define FOR_base32
#include "generated/flags.h"
void base32_main(void)
{
TT.n = 5;
TT.align = 7;
base32_init(toybuf);
loopfiles(toys.optargs, do_base_n);
}