From b6b5becf359370c7f32d8419bcf8f50a47fbe933 Mon Sep 17 00:00:00 2001 From: Moritz Röhrich Date: Thu, 7 Jan 2021 17:40:20 +0100 Subject: new toy: base32 Add new toy `base32`. Add tests for `base32`. base32 is added by adapting the base64 encode/decode function to also do base32 encoding/decoding. Then their respective main functions set up the global parameter `n` to be the number of bits used in the encoding (5 for base32 and 6 for base64) and `align` to align the result to a certain length via padding. These are deliberately kept as parameters to enable future expansion for other bases easily. --- lib/lib.c | 12 ++++++++++++ lib/lib.h | 1 + tests/base32.test | 24 ++++++++++++++++++++++++ toys/other/base64.c | 46 +++++++++++++++++++++++++++++++++++++--------- 4 files changed, 74 insertions(+), 9 deletions(-) create mode 100755 tests/base32.test diff --git a/lib/lib.c b/lib/lib.c index dfa4499f..1aa9b80d 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -870,6 +870,18 @@ void base64_init(char *p) *(p++) = '/'; } +// Init base32 table + +void base32_init(char *p) +{ + int i; + + for (i = 'A'; i != '8'; i++) { + if (i == 'Z'+1) i = '2'; + *(p++) = i; + } +} + int yesno(int def) { return fyesno(stdin, def); diff --git a/lib/lib.h b/lib/lib.h index 431ce5ad..1ba59ee3 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -255,6 +255,7 @@ void delete_tempfile(int fdin, int fdout, char **tempname); void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); void base64_init(char *p); +void base32_init(char *p); int yesno(int def); int fyesno(FILE *fp, int def); int qstrcmp(const void *a, const void *b); diff --git a/tests/base32.test b/tests/base32.test new file mode 100755 index 00000000..00bcffa9 --- /dev/null +++ b/tests/base32.test @@ -0,0 +1,24 @@ +#!/bin/bash + +[ -f testing.sh ] && . testing.sh + +# testing "name" "flags" "result" "infile" "stdin" + +testcmd "simple" "" "ONUW24DMMUFA====\n" "" "simple\n" +testcmd "file" "input" "ONUW24DMMUFA====\n" "simple\n" "" +testcmd "simple -d" "-d" "simple\n" "" "ONUW24DMMUFA====\n" +testcmd "file -d" "-d input" "simple\n" "ONUW24DMMUFA====" "" +testcmd "default wrap" "" \ + "K5SSO5TFEBZGK4DMMFRWKZBAORUGKIDENFWGS5DINF2W2IDUNBSXSIDON5ZG2YLMNR4SA5LTMUQH\nO2LUNAQEM33MM5SXEJ3TEBBXE6LTORQWY4ZO\n" \ + "" "We've replaced the dilithium they normally use with Folger's Crystals." +testcmd "multiline -d " "-d" \ + "We've replaced the dilithium they normally use with Folger's Crystals." "" \ + "K5SSO5TFEBZGK4DMMFRWKZBAORUGKIDENFWGS5DINF2W2IDUNBSXSIDON5ZG2YLMNR4SA5LTMUQH\nO2LUNAQEM33MM5SXEJ3TEBBXE6LTORQWY4ZO\n" + +testcmd "-w" "-w 10" \ + "JVQXEY3INF\nXGOIDUN4QH\nI2DFEBRGKY\nLUEBXWMIDB\nEBSGSZTGMV\nZGK3TUEBVW\nK5DUNRSSA3\n3GEBTGS43I\nFY======\n" \ + "" "Marching to the beat of a different kettle of fish." + +testcmd "-w0" "-w0 input" \ + "KZUWW2LOM5ZT6ICUNBSXEZJAMFUW4J3UEBXG6IDWNFVWS3THOMQGQZLSMUXCASTVON2CA5LTEBUG63TFON2CAZTBOJWWK4TTFYQFI2DFEB2G653OEB3WC4ZAMJ2XE3TJNZTSYIDUNBSSA5TJNRWGCZ3FOJZSA53FOJSSAZDFMFSC4ICUNBSXSIDENFSG4J3UEBXGKZLEEB2GQ33TMUQHG2DFMVYCAYLOPF3WC6JOEBKGQYLUE5ZSA33VOIQHG5DPOJ4SAYLOMQQHOZJHOJSSA43UNFRWW2LOM4QHI3ZANF2C4CQ=" \ + "Vikings? There ain't no vikings here. Just us honest farmers. The town was burning, the villagers were dead. They didn't need those sheep anyway. That's our story and we're sticking to it.\n" "" diff --git a/toys/other/base64.c b/toys/other/base64.c index ef7854a1..25e37d41 100644 --- a/toys/other/base64.c +++ b/toys/other/base64.c @@ -5,6 +5,7 @@ * 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" @@ -14,6 +15,18 @@ config BASE64 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) @@ -24,8 +37,9 @@ config BASE64 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) @@ -38,7 +52,7 @@ static void wraputchar(int c, int *x) }; } -static void do_base64(int fd, char *name) +static void do_base_n(int fd, char *name) { int out = 0, bits = 0, x = 0, i, len; char *buf = toybuf+128; @@ -49,8 +63,8 @@ static void do_base64(int fd, char *name) // If no more data, flush buffer if (!(len = xread(fd, buf, sizeof(toybuf)-128))) { if (!FLAG(d)) { - if (bits) wraputchar(toybuf[out<<(6-bits)], &x); - while (TT.total&3) wraputchar('=', &x); + if (bits) wraputchar(toybuf[out<<(TT.n-bits)], &x); + while (TT.total&TT.align) wraputchar('=', &x); if (x) xputc('\n'); } @@ -62,8 +76,8 @@ static void do_base64(int fd, char *name) if (buf[i] == '=') return; if ((x = stridx(toybuf, buf[i])) != -1) { - out = (out<<6) + x; - bits += 6; + out = (out<= 8) { putchar(out >> (bits -= 8)); out &= (1<= 6) { - wraputchar(toybuf[out >> (bits -= 6)], &x); + while (bits >= TT.n) { + wraputchar(toybuf[out >> (bits -= TT.n)], &x); out &= (1<