From: Ian Jackson Date: Sun, 17 Nov 2019 00:44:41 +0000 (+0000) Subject: base91-0.6.0.tar.gz downloaed just now X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=base91.git;a=commitdiff_plain;h=c4ccd63b1f4d8a556c4ad764a23364e4b7424338 base91-0.6.0.tar.gz downloaed just now From http://downloads.sourceforge.net/base91/base91-0.6.0.tar.gz Signed-off-by: Ian Jackson --- c4ccd63b1f4d8a556c4ad764a23364e4b7424338 diff --git a/AWK/README b/AWK/README new file mode 100644 index 0000000..ff1a834 --- /dev/null +++ b/AWK/README @@ -0,0 +1,16 @@ +This is a (slow) AWK implementation of the basE91 decoder. It decodes from +standard input to standard output. + +Example usage: + + awk -f b91dec.awk < file.b91 > file.bin + or + ./b91dec.awk < file.b91 > file.bin + + +Be careful on non-Unix systems! - During output, some ported versions of awk +automatically convert byte values of 0x0A to the native line break sequence of +the host system (e.g. 0x0D 0x0A under DOS/Windows). This can result in corrupt +binary files. +You should test on some examples and compare the output of b91dec.awk with the +original data before relying on it. diff --git a/AWK/b91dec.awk b/AWK/b91dec.awk new file mode 100755 index 0000000..8a15fc3 --- /dev/null +++ b/AWK/b91dec.awk @@ -0,0 +1,48 @@ +#!/usr/bin/awk -f + +# basE91 decoder +# Copyright (c) 2000-2006 Joachim Henke +# http://base91.sourceforge.net/ + +BEGIN { + b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\"" + for (i = 0; i < 256; ++i) { + --d[sprintf("%c", i)] + } + for (i = 0; i < 91; ++i) { + d[substr(b, i + 1, 1)] = i + } + b = 0 + n = 0 + v = -1 +} + +{ + l = length($0) + for (i = 1; i <= l; ++i) { + c = d[substr($0, i, 1)] + if (c < 0) { + continue + } + if (v < 0) { + v = c + } else { + v += c * 91 + b += v * 2 ^ n + n += v % 8192 > 88 ? 13 : 14 + do { + b -= c = b % 256 + printf "%c", c + b /= 256 + n -= 8 + } while (n > 7) + v = -1 + } + } +} + +END { + if (v + 1) { + printf "%c", b + v * 2 ^ n + } +} diff --git a/DOS-asm/b91enc.asm b/DOS-asm/b91enc.asm new file mode 100644 index 0000000..c4d00e9 --- /dev/null +++ b/DOS-asm/b91enc.asm @@ -0,0 +1,152 @@ +; basE91 encoder for DOS +; +; Copyright (c) 2005-2006 Joachim Henke +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; - Redistributions of source code must retain the above copyright notice, +; this list of conditions and the following disclaimer. +; - Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; - Neither the name of Joachim Henke nor the names of his contributors may +; be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +; POSSIBILITY OF SUCH DAMAGE. + +bits 16 +cpu 8086 +org 256 + + xor sp, sp + mov si, ld_0 ; create lookup table + mov bp, 90 +lc_0: + mov bx, 90 + mov ah, [bp + si] +lc_1: + mov al, [bx + si] + push ax + dec bx + jns lc_1 + dec bp + jns lc_0 + + inc bx + mov sp, a_stck +lc_2: + push bx + push bx + jmp short lc_5 +lc_3: + mov ax, [si] + cmp cl, 6 ; bits in queue + 8 < 14? + sbb dx, dx + inc si + mov ch, ah + add bp, dx + sbb dx, dx + xor ch, al + and ah, dl + and ch, dl + sub si, dx + xor ch, al + shl ax, cl + add cl, 8 + or bx, ax + test bp, bp + js lc_4 + + and bh, 0x1F ; keep 13 bits + and dl, 8 + and ah, 0x3F + cmp bx, byte 89 ; value in bit queue < 89? + sbb al, al + add dl, cl + and ah, al + mov cl, 13 + or bh, ah ; take 13 or 14 bits + sub cl, al + add bx, bx + mov ax, [bx + a_ltab] + mov bx, cx + add cl, 16 + sub cl, dl + sub dl, bl + shr bx, cl ; restore bit queue + mov cl, dl + stosw + dec bp + jns lc_3 +lc_4: + push bx + mov ah, 0x40 + push cx + mov bx, 1 + lea cx, [di - a_obuf] + mov dx, a_obuf + int 0x21 ; write to standard output + + dec bx +lc_5: + mov ah, 0x3F + mov cx, s_ibuf + mov dx, a_ibuf + int 0x21 ; read from standard input + + cld + pop cx + mov si, dx + mov di, a_obuf + pop bx + add bp, ax ; ax = 0 -> EOF + jc lc_3 + + push ax + test cl, cl + jz lc_6 + + cmp bx, byte 91 ; value in bit queue < 91? + sbb dx, dx + cmp cl, 8 ; less than 8 bits in queue? + sbb cx, cx + add bx, bx + and cx, dx + mov dx, a_obuf + mov ax, [bx + a_ltab] + inc cx + mov bx, 1 + inc cx + stosw + mov ah, 0x40 + int 0x21 ; write out 1 or 2 bytes +lc_6: + retn ; exit program +ld_0: + db 'ABCDEFGHIJKLM' + db 'NOPQRSTUVWXYZ' + db 'abcdefghijklm' + db 'nopqrstuvwxyz' + db '0123456789!#$' + db '%&()*+,./:;<=' + db '>?@[]^_`{|}~"' + + +a_stck equ ((lc_2 - $$) + 256) & 510 +a_ltab equ 48974 +a_obuf equ ((ld_0 - $$) + 257) & 510 +s_ibuf equ ((a_ltab - a_obuf - 2) << 4) / 29 +a_ibuf equ a_ltab - s_ibuf diff --git a/DOS-asm/readme.txt b/DOS-asm/readme.txt new file mode 100644 index 0000000..a3c0f47 --- /dev/null +++ b/DOS-asm/readme.txt @@ -0,0 +1,12 @@ +This is a compact 16-bit assembly implementation of the basE91 encoder for DOS. +It encodes from standard input to standard output. Minimum system requirements: +DOS 2.0, 8086 processor + +Example usage: + + b91enc < file.bin > file.b91 + + +Assemble with NASM [http://nasm.sourceforge.net/]: + + nasm -O2 -o b91enc.com b91enc.asm diff --git a/Java/b91cli.java b/Java/b91cli.java new file mode 100644 index 0000000..7d39990 --- /dev/null +++ b/Java/b91cli.java @@ -0,0 +1,181 @@ +/* + * basE91 command line front-end + * + * Copyright (c) 2000-2006 Joachim Henke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Joachim Henke nor the names of his contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import java.io.*; + +public class b91cli +{ + private static void encode(InputStream is, OutputStream os) + { + int s; + byte[] ibuf = new byte[53248]; + byte[] obuf = new byte[65536]; + basE91 b91 = new basE91(); + + try { + while ((s = is.read(ibuf)) > 0) { + s = b91.encode(ibuf, s, obuf); + os.write(obuf, 0, s); + } + s = b91.encEnd(obuf); + os.write(obuf, 0, s); + } catch (Exception e) { + System.err.println(e); + } + } + + private static void encodeWrap(InputStream is, OutputStream os) + { + int i, s; + int n = 0; + byte[] ibuf = new byte[53248]; + byte[] obuf = new byte[65536]; + char[] line = new char[76]; + basE91 b91 = new basE91(); + + try { + PrintStream ps = new PrintStream(os, false, "US-ASCII"); + + while ((s = is.read(ibuf)) > 0) { + s = b91.encode(ibuf, s, obuf); + for (i = 0; i < s; ++i) { + line[n++] = (char) obuf[i]; + if (n == 76) { + ps.println(line); + n = 0; + } + } + } + s = b91.encEnd(obuf); + for (i = 0; i < s; ++i) { + line[n++] = (char) obuf[i]; + if (n == 76) { + ps.println(line); + n = 0; + } + } + if (n > 0) + ps.println(new String(line, 0, n)); + } catch (Exception e) { + System.err.println(e); + } + } + + private static void decode(InputStream is, OutputStream os) + { + int s; + byte[] ibuf = new byte[65536]; + byte[] obuf = new byte[57344]; + basE91 b91 = new basE91(); + + try { + while ((s = is.read(ibuf)) > 0) { + s = b91.decode(ibuf, s, obuf); + os.write(obuf, 0, s); + } + s = b91.decEnd(obuf); + os.write(obuf, 0, s); + } catch (Exception e) { + System.err.println(e); + } + } + + private static void errExit(String msg) + { + System.err.println("syntax error - " + msg + "\nTry `-h' option for more information."); + System.exit(3); + } + + public static void main(String[] args) + { + int i; + boolean enc = true; + boolean lbr = true; + String ifn = null; + String ofn = null; + + for (i = 0; i < args.length; ++i) + if (args[i].length() == 2 && args[i].charAt(0) == '-') + switch (args[i].charAt(1)) { + case 'd': + enc = false; + break; + case 'u': + lbr = false; + break; + case 'h': + System.out.println("Usage: base91 [OPTION] infile [outfile]\n\n -d\tdecode a basE91 encoded file\n -u\tleave encoder output unformatted (disable line wrapping)\n -h\tdisplay this help and exit\n -V\toutput version information and exit"); + return; + case 'V': + System.out.println("base91 0.6.0\nCopyright (c) 2000-2006 Joachim Henke"); + return; + default: + errExit("invalid option: " + args[i]); + } + else if (ifn == null) + ifn = args[i]; + else if (ofn == null) + ofn = args[i]; + else + errExit("too many arguments: " + args[i]); + if (ifn == null) + errExit("file name missing"); + if (ofn == null) + if (enc) + ofn = ifn + (lbr ? "_b91.txt" : ".b91"); + else { + String lifn = ifn.toLowerCase(); + if (ifn.length() > 4 && lifn.endsWith(".b91")) + ofn = ifn.substring(0, ifn.length() - 4); + else if (ifn.length() > 8 && lifn.endsWith("_b91.txt")) + ofn = ifn.substring(0, ifn.length() - 8); + else + ofn = ifn + ".bin"; + } + + try { + FileInputStream ifs = new FileInputStream(ifn); + FileOutputStream ofs = new FileOutputStream(ofn); + + if (enc) + if (lbr) + encodeWrap(ifs, ofs); + else + encode(ifs, ofs); + else + decode(ifs, ofs); + ifs.close(); + ofs.close(); + } catch (Exception e) { + System.err.println(e); + } + } +} diff --git a/Java/basE91.java b/Java/basE91.java new file mode 100644 index 0000000..56d7fda --- /dev/null +++ b/Java/basE91.java @@ -0,0 +1,137 @@ +/* + * basE91 encoding/decoding routines + * + * Copyright (c) 2000-2006 Joachim Henke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Joachim Henke nor the names of his contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +public class basE91 +{ + private int ebq, en, dbq, dn, dv; + public final byte[] enctab; + private final byte[] dectab; + + public int encode(byte[] ib, int n, byte[] ob) + { + int i, c = 0; + + for (i = 0; i < n; ++i) { + ebq |= (ib[i] & 255) << en; + en += 8; + if (en > 13) { + int ev = ebq & 8191; + + if (ev > 88) { + ebq >>= 13; + en -= 13; + } else { + ev = ebq & 16383; + ebq >>= 14; + en -= 14; + } + ob[c++] = enctab[ev % 91]; + ob[c++] = enctab[ev / 91]; + } + } + return c; + } + + public int encEnd(byte[] ob) + { + int c = 0; + + if (en > 0) { + ob[c++] = enctab[ebq % 91]; + if (en > 7 || ebq > 90) + ob[c++] = enctab[ebq / 91]; + } + encReset(); + return c; + } + + public void encReset() + { + ebq = 0; + en = 0; + } + + public int decode(byte[] ib, int n, byte[] ob) + { + int i, c = 0; + + for (i = 0; i < n; ++i) { + if (dectab[ib[i]] == -1) + continue; + if (dv == -1) + dv = dectab[ib[i]]; + else { + dv += dectab[ib[i]] * 91; + dbq |= dv << dn; + dn += (dv & 8191) > 88 ? 13 : 14; + do { + ob[c++] = (byte) dbq; + dbq >>= 8; + dn -= 8; + } while (dn > 7); + dv = -1; + } + } + return c; + } + + public int decEnd(byte[] ob) + { + int c = 0; + + if (dv != -1) + ob[c++] = (byte) (dbq | dv << dn); + decReset(); + return c; + } + + public void decReset() + { + dbq = 0; + dn = 0; + dv = -1; + } + + public basE91() + { + int i; + String ts = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\""; + + enctab = ts.getBytes(); + dectab = new byte[256]; + for (i = 0; i < 256; ++i) + dectab[i] = -1; + for (i = 0; i < 91; ++i) + dectab[enctab[i]] = (byte) i; + encReset(); + decReset(); + } +} diff --git a/Java/build_jar.sh b/Java/build_jar.sh new file mode 100755 index 0000000..bd54b3e --- /dev/null +++ b/Java/build_jar.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +javac -encoding US-ASCII -g:none -source 1.3 -target 1.2 basE91.java b91cli.java && \ +jar cvfm base91.jar manifest.mf b91cli.class basE91.class license.txt readme.txt diff --git a/Java/license.txt b/Java/license.txt new file mode 100644 index 0000000..8b952bd --- /dev/null +++ b/Java/license.txt @@ -0,0 +1,25 @@ +Copyright (c) 2000-2006 Joachim Henke +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of Joachim Henke nor the names of his contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Java/manifest.mf b/Java/manifest.mf new file mode 100644 index 0000000..b06ff67 --- /dev/null +++ b/Java/manifest.mf @@ -0,0 +1,4 @@ +Main-Class: b91cli +Package-Title: basE91 command line tool +Package-Version: 0.6.0 +Package-Vendor: Joachim Henke diff --git a/Java/readme.txt b/Java/readme.txt new file mode 100644 index 0000000..bc5a3ac --- /dev/null +++ b/Java/readme.txt @@ -0,0 +1,26 @@ +This is an implementation of the basE91 encoder and decoder in Java. + +Syntax: + java -jar base91.jar [OPTION] infile [outfile] + +Options: + +-d decode a basE91 encoded file; + all non-alphabet characters (such as newlines) are ignored + +-u leave encoder output unformatted; + i. e., disable line wrapping after 76 characters + +-h display short help and exit + +-V output version information and exit + + +If no outfile is given for encoding, it defaults to `infile_b91.txt' (or to +`infile.b91' with the `-u' switch). +On decoding, the added file extension is removed to generate the name for +outfile; otherwise, if infile hasn't a default extension, the decoded data is +written to `infile.bin'. + +For further information visit the basE91 home page at +http://base91.sourceforge.net/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e4a656c --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2000-2006 Joachim Henke +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of Joachim Henke nor the names of his contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..246aede --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +CFLAGS = -Wall -W -O2 +LDFLAGS = -s + +CC = gcc +INSTALL = install +INSTALL_DATA = $(INSTALL) -m 444 +INSTALL_PROGRAM = $(INSTALL) -m 555 + +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +mandir = $(prefix)/share/man +man1dir = $(mandir)/man1 +manext = .1 + +BIN = base91 + +.PHONY: all install check clean + +all: $(BIN) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +base91: cli.o base91.o + $(CC) $(LDFLAGS) -o $@ $^ + +install: all + mkdir -p $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) base91 $(DESTDIR)$(bindir)/base91 + ln -sf base91 $(DESTDIR)$(bindir)/b91dec + ln -sf base91 $(DESTDIR)$(bindir)/b91enc + mkdir -p $(DESTDIR)$(man1dir) + $(INSTALL_DATA) base91.1 $(DESTDIR)$(man1dir)/base91$(manext) + ln -sf base91$(manext) $(DESTDIR)$(man1dir)/b91dec$(manext) + ln -sf base91$(manext) $(DESTDIR)$(man1dir)/b91enc$(manext) + +check: all + cd test && $(MAKE) + +clean: + -rm -f *.o $(BIN) core + cd test && $(MAKE) clean diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..98dbf22 --- /dev/null +++ b/NEWS @@ -0,0 +1,64 @@ +[0.6.0] 2006-11-01 +* basE91 encoding/decoding routines restructured to be thread-safe +* lots of type fixes +* new core utility is `base91', with a behaviour similar to GNU base64 +* introduce `-w' switch for wrapping encoded output lines after given length +* long option handling +* use standard I/O functions for better portability +* MinGW compatibility code added +* minor extensions to `make check' +* Java-tool wraps output lines by default; can be avoided with the `-u' switch +* license changed to BSD + +[0.5.2] 2006-08-25 +* code cleanup +* encoder for DOS rewritten to be faster and compatible down to Intel 8086 + +[0.5.1] 2005-10-05 +* Java-b91enc now handles file extensions case insensitively +* native DOS version of basE91 encoder added + +[0.5.0] 2005-06-24 +* ATTENTION: this version breaks backward compatibility because the basE91 + alphabet was changed to reduce the occurrence of double quotes - sorry, I + should have done this long before +* b91dec is installed as a link to b91enc +* `-e' option added (complement to `-d') +* build system should be more portable now + +[0.4.2] 2005-05-16 +* AWK basE91 decoder no longer depends on GNU extensions +* Java byte code removed (distributed separately in a jar file) + +[0.4.1] 2005-05-07 +* some code cleanup +* Java-b91enc can break encoded output to lines of 76 characters (`-b' switch) + +[0.4.0] 2005-04-26 +* improved encoder behaviour on stream ends (can save one byte sometimes) +* allocate buffer memory dynamically; use overlapping buffers +* new `-m' switch can be used for testing +* verbose mode extended: `-vv' shows memory statistics +* `make check' implemented - runs some basic tests + +[0.3.1] 2005-04-19 +* b91enc has a verbose mode now (`-v' switch) +* Java-b91enc accepts command line syntax with only one FILE argument again + +[0.3.0] 2005-04-17 +* the code was restructured to allow a more universal use of the basE91 backend +* version switch changed to `-V' which is more common - sorry for that +* `make install' is possible now +* changed Java-b91enc to be a bit more similar to the C version +* implementation in PHP added + +[0.2.3] 2005-04-11 +* man page included (thanks to Kei!) +* version (-v) switch added + +[0.2.2] 2005-04-10 +* fixed a bug in decoder that could result in corrupt output on 64-bit systems +* Java class files included + +[0.2.1] 2005-04-09 +* first public release diff --git a/PHP4/README b/PHP4/README new file mode 100644 index 0000000..b357bad --- /dev/null +++ b/PHP4/README @@ -0,0 +1,40 @@ +base91_encode -- Encodes data with basE91 + + string base91_encode ( string data ) + +base91_encode() returns data encoded with basE91. This encoding is designed to +make binary data survive transport through transport layers that are not 8-bit +clean, such as mail bodies. + +basE91-encoded data takes at most 23% more space than the original data. + +Example: + + +This example will produce: + +nX,<:WRT%yV%!5:maref3+1RrUb64^M + +----- + +base91_decode -- Decodes data encoded with basE91 + + string base91_decode ( string encoded_data ) + +base91_decode() decodes encoded_data ignoring non-alphabet characters and +returns the original data. The returned data may be binary. + +Example: + + +This example will produce: + +This is an encoded string diff --git a/PHP4/base91.php b/PHP4/base91.php new file mode 100644 index 0000000..ea34f03 --- /dev/null +++ b/PHP4/base91.php @@ -0,0 +1,71 @@ +', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"' +); +$b91_dectab = array_flip($b91_enctab); + +function base91_decode($d) +{ + global $b91_dectab; + $l = strlen($d); + $v = -1; + for ($i = 0; $i < $l; ++$i) { + $c = $b91_dectab[$d{$i}]; + if (!isset($c)) + continue; + if ($v < 0) + $v = $c; + else { + $v += $c * 91; + $b |= $v << $n; + $n += ($v & 8191) > 88 ? 13 : 14; + do { + $o .= chr($b & 255); + $b >>= 8; + $n -= 8; + } while ($n > 7); + $v = -1; + } + } + if ($v + 1) + $o .= chr(($b | $v << $n) & 255); + return $o; +} + +function base91_encode($d) +{ + global $b91_enctab; + $l = strlen($d); + for ($i = 0; $i < $l; ++$i) { + $b |= ord($d{$i}) << $n; + $n += 8; + if ($n > 13) { + $v = $b & 8191; + if ($v > 88) { + $b >>= 13; + $n -= 13; + } else { + $v = $b & 16383; + $b >>= 14; + $n -= 14; + } + $o .= $b91_enctab[$v % 91] . $b91_enctab[$v / 91]; + } + } + if ($n) { + $o .= $b91_enctab[$b % 91]; + if ($n > 7 || $b > 90) + $o .= $b91_enctab[$b / 91]; + } + return $o; +} +?> diff --git a/README b/README new file mode 100644 index 0000000..731eaaa --- /dev/null +++ b/README @@ -0,0 +1,75 @@ +basE91 - converting binary data to ASCII text +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Copyright (c) 2000-2006 Joachim Henke + + +basE91 is an advanced method for encoding binary data as ASCII characters. It +is similar to UUencode or base64, but is more efficient. The overhead produced +by basE91 depends on the input data. It amounts at most to 23% (versus 33% for +base64) and can range down to 14%, which typically occurs on 0-byte blocks. +This makes basE91 very useful for transferring larger files over binary +insecure connections like e-mail or terminal lines. + +The current algorithm has been written with portability and simplicity in mind +an is therefore not necessarily optimised for speed. + + +* Alphabet + +As the name suggests, basE91 needs 91 characters to represent the encoded +binary data in ASCII. From the 94 printable ASCII characters (0x21-0x7E), the +following three ones have been omitted to build the basE91 alphabet: + +- (dash, 0x2D) +' (apostrophe, 0x27) +\ (backslash, 0x5C) + +The translation table is composed of the remaining characters as shown below. + + 0 A 13 N 26 a 39 n 52 0 65 % 78 > + 1 B 14 O 27 b 40 o 53 1 66 & 79 ? + 2 C 15 P 28 c 41 p 54 2 67 ( 80 @ + 3 D 16 Q 29 d 42 q 55 3 68 ) 81 [ + 4 E 17 R 30 e 43 r 56 4 69 * 82 ] + 5 F 18 S 31 f 44 s 57 5 70 + 83 ^ + 6 G 19 T 32 g 45 t 58 6 71 , 84 _ + 7 H 20 U 33 h 46 u 59 7 72 . 85 ` + 8 I 21 V 34 i 47 v 60 8 73 / 86 { + 9 J 22 W 35 j 48 w 61 9 74 : 87 | +10 K 23 X 36 k 49 x 62 ! 75 ; 88 } +11 L 24 Y 37 l 50 y 63 # 76 < 89 ~ +12 M 25 Z 38 m 51 z 64 $ 77 = 90 " + + +* Building + +1. `cd' to the directory containing the package's source code and type `make' + to compile the package + +2. optionally, type `make check' to run any self-tests that come with the + package + +3. type `make install' to install the program and documentation in `/usr/local' + (to specify another installation prefix than `/usr/local', type + `make prefix=PATH install' instead) + +4. you can remove the program binaries and object files from the source code + directory by typing `make clean' + + +* Developer + +Joachim Henke + + +* Copying + +All source code in this package is released under the terms of the BSD license. +See the file LICENSE for copying permission. + + +* See also + +Please visit the basE91 home page [http://base91.sourceforge.net/] for the +latest version and pre-compiled binaries. diff --git a/base91.1 b/base91.1 new file mode 100644 index 0000000..3f31ded --- /dev/null +++ b/base91.1 @@ -0,0 +1,57 @@ +.TH BASE91 1 "November 2006" "base91 0.6.0" basE91 +.SH NAME +base91, b91enc, b91dec \- basE91 encode/decode data +.SH SYNOPSIS +.B base91 +.RI [ OPTION "]... [" FILE ] +.SH DESCRIPTION +Convert binary data in FILE to plain ASCII text (or vice versa), writing to +standard output. With no FILE, or when FILE is \-, read standard input. +.TP +.BR \-d ", " \-\-decode +decode data (default for +.BR b91dec ); +all non\-alphabet characters (such as newlines) are ignored +.TP +.BI "\-m " SIZE +use maximum SIZE bytes of main memory for buffers (default 64K); +SIZE may be followed by a multiplicative suffix: +.I K +1024, +.I M +1024*1024 +.TP +.BR \-o ", " \-\-output =\fIFILE\fR +write result to FILE instead of standard output +.TP +.BR \-v ", " \-\-verbose +run in verbose mode and write some statistics to standard error; +use it twice to increase verbosity +.TP +.BR \-w ", " \-\-wrap =\fICOLS\fR +wrap encoded lines after COLS characters (default 76); +use 0 to disable line wrapping (default for +.BR b91enc ) +.TP +.B \-\-help +prints out the available program options +.TP +.B \-\-version +output version information and exit +.PP +basE91 is an advanced method for encoding binary data as ASCII characters. It +is similar to UUencode or base64, but is more efficient. The overhead produced +by basE91 depends on the input data. It amounts at most to 23% (versus 33% for +base64) and can range down to 14%, which typically occurs on 0\-byte blocks. +This makes basE91 very useful for transferring larger files over binary +insecure connections like e\-mail or terminal lines. +.SH AUTHOR +Written by Joachim Henke. +.SH "REPORTING BUGS" +Report bugs to . +.SH COPYRIGHT +Copyright (c) 2000\-2006 Joachim Henke +.SH "SEE ALSO" +base64(1), uuencode(1) + +http://base91.sourceforge.net/ diff --git a/base91.c b/base91.c new file mode 100644 index 0000000..3d9d7ea --- /dev/null +++ b/base91.c @@ -0,0 +1,159 @@ +/* + * basE91 encoding/decoding routines + * + * Copyright (c) 2000-2006 Joachim Henke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Joachim Henke nor the names of his contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base91.h" + +const unsigned char enctab[91] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$', + '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=', + '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"' +}; +const unsigned char dectab[256] = { + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 74, 75, 76, 77, 78, 79, + 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 81, 91, 82, 83, 84, + 85, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 86, 87, 88, 89, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91 +}; + +void basE91_init(struct basE91 *b) +{ + b->queue = 0; + b->nbits = 0; + b->val = -1; +} + +size_t basE91_encode(struct basE91 *b, const void *i, size_t len, void *o) +{ + const unsigned char *ib = i; + unsigned char *ob = o; + size_t n = 0; + + while (len--) { + b->queue |= *ib++ << b->nbits; + b->nbits += 8; + if (b->nbits > 13) { /* enough bits in queue */ + unsigned int val = b->queue & 8191; + + if (val > 88) { + b->queue >>= 13; + b->nbits -= 13; + } else { /* we can take 14 bits */ + val = b->queue & 16383; + b->queue >>= 14; + b->nbits -= 14; + } + ob[n++] = enctab[val % 91]; + ob[n++] = enctab[val / 91]; + } + } + + return n; +} + +/* process remaining bits from bit queue; write up to 2 bytes */ + +size_t basE91_encode_end(struct basE91 *b, void *o) +{ + unsigned char *ob = o; + size_t n = 0; + + if (b->nbits) { + ob[n++] = enctab[b->queue % 91]; + if (b->nbits > 7 || b->queue > 90) + ob[n++] = enctab[b->queue / 91]; + } + b->queue = 0; + b->nbits = 0; + b->val = -1; + + return n; +} + +size_t basE91_decode(struct basE91 *b, const void *i, size_t len, void *o) +{ + const unsigned char *ib = i; + unsigned char *ob = o; + size_t n = 0; + unsigned int d; + + while (len--) { + d = dectab[*ib++]; + if (d == 91) + continue; /* ignore non-alphabet chars */ + if (b->val == -1) + b->val = d; /* start next value */ + else { + b->val += d * 91; + b->queue |= b->val << b->nbits; + b->nbits += (b->val & 8191) > 88 ? 13 : 14; + do { + ob[n++] = b->queue; + b->queue >>= 8; + b->nbits -= 8; + } while (b->nbits > 7); + b->val = -1; /* mark value complete */ + } + } + + return n; +} + +/* process remaining bits; write at most 1 byte */ + +size_t basE91_decode_end(struct basE91 *b, void *o) +{ + unsigned char *ob = o; + size_t n = 0; + + if (b->val != -1) + ob[n++] = b->queue | b->val << b->nbits; + b->queue = 0; + b->nbits = 0; + b->val = -1; + + return n; +} diff --git a/base91.h b/base91.h new file mode 100644 index 0000000..7a44a60 --- /dev/null +++ b/base91.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2000-2006 Joachim Henke + * + * For conditions of distribution and use, see copyright notice in base91.c + */ + +#ifndef BASE91_H +#define BASE91_H 1 + +#include + +struct basE91 { + unsigned long queue; + unsigned int nbits; + int val; +}; + +void basE91_init(struct basE91 *); + +size_t basE91_encode(struct basE91 *, const void *, size_t, void *); + +size_t basE91_encode_end(struct basE91 *, void *); + +size_t basE91_decode(struct basE91 *, const void *, size_t, void *); + +size_t basE91_decode_end(struct basE91 *, void *); + +#endif /* base91.h */ diff --git a/cli.c b/cli.c new file mode 100644 index 0000000..f365991 --- /dev/null +++ b/cli.c @@ -0,0 +1,294 @@ +/* + * basE91 command line front-end + * + * Copyright (c) 2000-2006 Joachim Henke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Joachim Henke nor the names of his contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#endif +#include +#include "base91.h" + +#define FLG_D 1 +#define FLG_V 2 +#define FLG_VV 4 + +static char status[32]; +static const char *progname; +static char *ibuf, *obuf; +static size_t ibuf_size, llen; +static struct basE91 b91; + +static void stream_b91enc_p(void) +{ + size_t itotal = 0; + size_t ototal = 0; + size_t s; + + while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { + itotal += s; + s = basE91_encode(&b91, ibuf, s, obuf); + ototal += s; + fwrite(obuf, 1, s, stdout); + } + s = basE91_encode_end(&b91, obuf); /* empty bit queue */ + ototal += s; + fwrite(obuf, 1, s, stdout); + + sprintf(status, "\t%.2f%%\n", itotal ? (float) ototal / itotal * 100.0 : 1.0); +} + +static void stream_b91enc_w(void) +{ + size_t l = llen; + size_t ltotal = 0; + size_t i, s; + char x; + + while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { + s = basE91_encode(&b91, ibuf, s, obuf); + for (i = 0; l <= s; l += llen) { + x = obuf[l]; + obuf[l] = '\0'; + puts(obuf + i); + ++ltotal; + obuf[l] = x; + i = l; + } + fwrite(obuf + i, 1, s - i, stdout); + l -= s; + } + s = basE91_encode_end(&b91, obuf); + if (s || l < llen) { + obuf[s] = '\0'; + if (s > l) { + x = obuf[1]; + obuf[1] = '\0'; + puts(obuf); + ++ltotal; + obuf[0] = x; + } + puts(obuf); + ++ltotal; + } + + sprintf(status, "\t%lu lines\n", (unsigned long) ltotal); +} + +static void stream_b91dec(void) +{ + size_t s; + + while ((s = fread(ibuf, 1, ibuf_size, stdin)) > 0) { + s = basE91_decode(&b91, ibuf, s, obuf); + fwrite(obuf, 1, s, stdout); + } + s = basE91_decode_end(&b91, obuf); /* empty bit queue */ + fwrite(obuf, 1, s, stdout); + + sprintf(status, "done\n"); +} + +static int init_flags(const char *p) +{ + size_t l = strlen(p); + + if (l > 5) { + progname = p + l - 6; + if (!strcmp(progname, "b91enc")) + return 0; + if (!strcmp(progname, "b91dec")) + return FLG_D; + } + llen = 76; + progname = "base91"; + + return 0; +} + +int main(int argc, char **argv) +{ + size_t buf_size = 65536; /* buffer memory defaults to 64 KiB */ + int flags = init_flags(*argv); + char *ifile = "from standard input"; + char *ofile = NULL; + int opt; + struct option longopts[8] = { + {"decode", no_argument, NULL, 'd'}, + {"output", required_argument, NULL, 'o'}, + {"verbose", no_argument, NULL, 'v'}, + {"wrap", required_argument, NULL, 'w'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; + + while ((opt = getopt_long(argc, argv, "dem:o:vw:hV", longopts, NULL)) != -1) + switch (opt) { + case 'd': + flags |= FLG_D; + break; + case 'e': + flags &= ~FLG_D; + break; + case 'm': + { + char *t; + long l = strtol(optarg, &t, 0); + + if (t == optarg || strlen(t) > 1 || l < 0) { + fprintf(stderr, "invalid SIZE argument: `%s'\n", optarg); + return EXIT_FAILURE; + } + buf_size = l; + switch (*t | 32) { + case ' ': + case 'b': + break; + case 'k': + buf_size <<= 10; + break; + case 'm': + buf_size <<= 20; + break; + default: + fprintf(stderr, "invalid SIZE suffix: `%s'\n", t); + return EXIT_FAILURE; + } + } + break; + case 'o': + if (strcmp(optarg, "-")) + ofile = optarg; + break; + case 'v': + flags |= (flags & FLG_V) ? FLG_VV : FLG_V; + break; + case 'w': + { + char *t; + long l = strtol(optarg, &t, 0); + + if (*t || l < 0) { + fprintf(stderr, "invalid number of columns: `%s'\n", optarg); + return EXIT_FAILURE; + } + llen = l; + } + break; + case 'h': + printf("Usage: %s [OPTION]... [FILE]\n" + "basE91 encode or decode FILE, or standard input, to standard output.\n", progname); + puts("\n -d, --decode\t\tdecode data\n" + " -m SIZE\t\tuse SIZE bytes of memory for buffers (suffixes b, K, M)\n" + " -o, --output=FILE\twrite to FILE instead of standard output\n" + " -v, --verbose\t\tverbose mode\n" + " -w, --wrap=COLS\twrap encoded lines after COLS characters (default 76)\n" + " --help\t\tdisplay this help and exit\n" + " --version\t\toutput version information and exit\n\n" + "With no FILE, or when FILE is -, read standard input."); + return EXIT_SUCCESS; + case 'V': + printf("%s 0.6.0\nCopyright (c) 2000-2006 Joachim Henke\n", progname); + return EXIT_SUCCESS; + default: + fprintf(stderr, "Try `%s --help' for more information.\n", *argv); + return EXIT_FAILURE; + } + + if (flags & FLG_D) { + ibuf_size = (buf_size - 1) << 3; + if (ibuf_size < 15) { + fputs("SIZE must be >= 3 for decoding\n", stderr); + return EXIT_FAILURE; + } + ibuf_size /= 15; + } else { + ibuf_size = (buf_size - 2) << 4; + if (ibuf_size < 29) { + fputs("SIZE must be >= 4 for encoding\n", stderr); + return EXIT_FAILURE; + } + ibuf_size /= 29; + } + + if (optind < argc && strcmp(argv[optind], "-")) { + ifile = argv[optind]; + if (freopen(ifile, "r", stdin) != stdin) { + perror(ifile); + return EXIT_FAILURE; + } + } + if (ofile) + if (freopen(ofile, "w", stdout) != stdout) { + perror(ofile); + return EXIT_FAILURE; + } + + if (flags & FLG_VV) + fprintf(stderr, "using %lu bytes for buffers; input buffer: %lu bytes\n", (unsigned long) buf_size, (unsigned long) ibuf_size); + obuf = malloc(buf_size); + if (!obuf) { + fputs("failed to allocate buffer memory\n", stderr); + return EXIT_FAILURE; + } + + basE91_init(&b91); +#ifdef _WIN32 + _setmode(_fileno(stdin), _O_BINARY); +#endif + + if (flags & FLG_D) { +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + ibuf = obuf + 1; /* create overlapping buffers to use memory efficiently */ + if (flags & FLG_V) + fprintf(stderr, "decoding %s ...", ifile); + stream_b91dec(); + } else { + ibuf = obuf + buf_size - ibuf_size; /* partial overlap */ + if (flags & FLG_V) + fprintf(stderr, "encoding %s ...", ifile); + if (llen) + stream_b91enc_w(); + else + stream_b91enc_p(); + } + free(obuf); + + if (flags & FLG_V) + fputs(status, stderr); + + return EXIT_SUCCESS; +} diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..48e3906 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,11 @@ +SHELL = /bin/sh + +.PHONY: all clean + +all: + ln -sf ../base91 b91enc + ln -sf ../base91 b91dec + $(SHELL) test.sh + +clean: + -rm -f b91??c *.b91 *.dat core diff --git a/test/test.sh b/test/test.sh new file mode 100644 index 0000000..cb79d40 --- /dev/null +++ b/test/test.sh @@ -0,0 +1,88 @@ +fail_exit() +{ + echo 'FAILED!' + exit 1 +} + +T='--------------------------------------+' + +./b91enc --version || fail_exit +echo -n ' + +extracting test files...' +echo '?/9f4iG0)z4jY;<$:B$AvWAAoB:CgALvDCeR+t bit0.dat && \ +echo '?/9f4iG0)z4jZgv|?AUYRAgA%AAAUA:y5L9LcoHE8HJI_yGIJ>T' | ./b91dec | bunzip2 > bit1.dat && \ +echo '71kS$5F/VZC0+Zw,c%df~>T1XkEvl{weS1NQ@@3Gd*`P2p~)^4>yP{Y9MFo.Q2=Mmsk:"lhR%87Ey_GRP +7hn_L73QVn>5CK0{6eHmBBtzP05[`PG3*"+n(bE$S";_b^gU5D87O,QjqW3wVc(_T8_:O{8P$9~{n7"SiU;Ca{w_;HB6L&u2W8M>ScI +aP#E.:novN/#Mk$STQeM^dSp5~JKkb3[t5_*3q&V/Z7aVdFPJ#P&TR3#`W+;&GpWk9CHq%R|fV~(K:g6_Du~m +j7S?;hnI$xFkGTDRJSJ#NNu_;(]ud#f3{1Q|;jH4l{Ql^mi]*jH>mCqmSW,Bx4^MBrnOtoa4gbM7m3S:OMQ4nt.un+)Zelc,Eoa|c!yN"3dV3b9YY2opW= +VS&}g7RI#0g?^mT#@#;Q%kmT2gGX8.*H;^Dywb$(o(t;/_#j8Vi*djlobF!Xw)B2lLV_sio/`z1zu^+^m9D~At(UH|,6o=j6kT(=Cz8q6(FBOm~&+F*,IgYH;XtV+,ejB".y`K9!2VxGi?YeQs+q9Ses]Qt +RzDX;Oyx]$Tcm;[GT4Auh}yN+%:}Q_xv5_B[/q30b!qFIn>w{^w`Qa99`=r0eo&uZFyq*` +dg.h"YJiW)t5BaO;?liP7Y|)o|]9KwM`rZO1p#}zYnX|.C(+P.RXy>T0XG^58"DO8Su/5MElg)J>eU,BjzB5}et|m+4>$GdR<(_[PUxc^o|c2L{w~mE@SZ.FH +;(=m1zJIMyYbz8z0=gf*;)WDk:3@7^YN&i1|MVarqV)qe]x9kJ)OPi&F``3?|P:(Fg$1(P2{xf0yf$WBU!.YmwYIT +F)^pdagK0(P~/96zGoD,QZlX]"`h/U`^ZWZeJ.c:XQ!WAz(Z|&2/E3)*V?vAb>?MUV5*T8i3u)apx`5<8J`bopXm> +*J,^8m.Ldfyj~KR#mt*&Z3a]N9WUT+^c2*@07TM:ATg(D)YMiSR[RTll_7DB3.HhUzKL:N0.:%J,<(_$0Ab{``OaN +43R:29/1$KXzs2%58B]G,h*r$Z/PqQqwh*sY.o(;Kkqw`1N^;JFk!;^?V+6/7irU+h._wN},b?.O.8t#:prfx9ZEE +t2AWg56N]g6MF0Bs7X^07[RwvgwxT@4RLk#SXzXj74XT93xa=$c0Sgi6z{apd:[5sDmwG;&jKSGGR.=c9qS$u[S:y +wM|buns:@)g|V@|QGD9wipn#u*HCFK7W}iD}f|E{h@PR@2+m%nN>u+"+>x&3iF+0`2GE03Gg;K`[.E[X4Swjchxf6 +LusH!p1)[}$SyFI"w|fztPfp*<~6Bu&1(.0XH68BX?a9mFcGoT>~qd7qtf)+v.o9(IAL7|jz32K"9d1Nh*1},xKnvFBHnD&1fv9+h,+nww+PRv7I2wU)B`nty%~eJ2OvRIa^k@T2 +*Y:8fa@pLgwFy,[Ea$di~YWC]4)j&3=B0nZn())A|p,70Y02g3ArYWjs+U' | ./b91enc -do rnd0.dat && \ +./b91enc --decode -o rnd1.dat rnd0.dat && echo ' OK' || fail_exit + +echo " +basE91 encode files: + ++-- best case --$T" +./b91enc -m 5k -vv --output=bit0.b91 bit0.dat +echo "+-- worst case -$T" +./b91enc -m 3k -vv --output=bit1.b91 bit1.dat +echo "+-- random data $T" +./b91enc -m 96 -vv --output=rnd0.b91 rnd0.dat +./b91enc -m 72 -vv --output=rnd1.b91 rnd1.dat + +echo ' +comparing check sums...' +cksum rnd?.dat *.b91 | while read C S F +do + echo -n "$F " + case $F in + rnd0.dat) V='15559944992141';; + rnd1.dat) V='3514104192626';; + bit0.b91) V='33531953171198370';; + bit1.b91) V='5394938771290552';; + rnd0.b91) V='32051515602633';; + rnd1.b91) V='2018291165770';; + esac + test $V = "$C$S" && echo OK || exit 1 +done || fail_exit +echo " +basE91 decode and compare: + ++-- best case --$T" +fold -w 83 bit0.b91 | ./b91dec -vvm 2K | cmp bit0.dat && echo PASSED || fail_exit +echo "+-- worst case -$T" +fold -w 79 bit1.b91 | ./b91dec -vvm 1K | cmp bit1.dat && echo PASSED || fail_exit +echo "+-- random data $T" +fold -w 73 rnd0.b91 | ./b91dec -vvm 89 | cmp rnd0.dat && echo PASSED || fail_exit +fold -w 71 rnd1.b91 | ./b91dec -vvm 73 | cmp rnd1.dat && echo PASSED || fail_exit + +echo ' +================ +all tests passed +================ +'