--- /dev/null
+/base91
+/lentest
+*.o
+/test/b91dec
+/test/b91enc
+/test/lentest
+/test/*.dat
+/test/*.b91
--- /dev/null
+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.
--- /dev/null
+#!/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
+ }
+}
--- /dev/null
+; basE91 encoder for DOS\r
+;\r
+; Copyright (c) 2005-2006 Joachim Henke\r
+; All rights reserved.\r
+;\r
+; Redistribution and use in source and binary forms, with or without\r
+; modification, are permitted provided that the following conditions are met:\r
+;\r
+; - Redistributions of source code must retain the above copyright notice,\r
+; this list of conditions and the following disclaimer.\r
+; - Redistributions in binary form must reproduce the above copyright notice,\r
+; this list of conditions and the following disclaimer in the documentation\r
+; and/or other materials provided with the distribution.\r
+; - Neither the name of Joachim Henke nor the names of his contributors may\r
+; be used to endorse or promote products derived from this software without\r
+; specific prior written permission.\r
+;\r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+; POSSIBILITY OF SUCH DAMAGE.\r
+\r
+bits 16\r
+cpu 8086\r
+org 256\r
+\r
+ xor sp, sp\r
+ mov si, ld_0 ; create lookup table\r
+ mov bp, 90\r
+lc_0:\r
+ mov bx, 90\r
+ mov ah, [bp + si]\r
+lc_1:\r
+ mov al, [bx + si]\r
+ push ax\r
+ dec bx\r
+ jns lc_1\r
+ dec bp\r
+ jns lc_0\r
+\r
+ inc bx\r
+ mov sp, a_stck\r
+lc_2:\r
+ push bx\r
+ push bx\r
+ jmp short lc_5\r
+lc_3:\r
+ mov ax, [si]\r
+ cmp cl, 6 ; bits in queue + 8 < 14?\r
+ sbb dx, dx\r
+ inc si\r
+ mov ch, ah\r
+ add bp, dx\r
+ sbb dx, dx\r
+ xor ch, al\r
+ and ah, dl\r
+ and ch, dl\r
+ sub si, dx\r
+ xor ch, al\r
+ shl ax, cl\r
+ add cl, 8\r
+ or bx, ax\r
+ test bp, bp\r
+ js lc_4\r
+\r
+ and bh, 0x1F ; keep 13 bits\r
+ and dl, 8\r
+ and ah, 0x3F\r
+ cmp bx, byte 89 ; value in bit queue < 89?\r
+ sbb al, al\r
+ add dl, cl\r
+ and ah, al\r
+ mov cl, 13\r
+ or bh, ah ; take 13 or 14 bits\r
+ sub cl, al\r
+ add bx, bx\r
+ mov ax, [bx + a_ltab]\r
+ mov bx, cx\r
+ add cl, 16\r
+ sub cl, dl\r
+ sub dl, bl\r
+ shr bx, cl ; restore bit queue\r
+ mov cl, dl\r
+ stosw\r
+ dec bp\r
+ jns lc_3\r
+lc_4:\r
+ push bx\r
+ mov ah, 0x40\r
+ push cx\r
+ mov bx, 1\r
+ lea cx, [di - a_obuf]\r
+ mov dx, a_obuf\r
+ int 0x21 ; write to standard output\r
+\r
+ dec bx\r
+lc_5:\r
+ mov ah, 0x3F\r
+ mov cx, s_ibuf\r
+ mov dx, a_ibuf\r
+ int 0x21 ; read from standard input\r
+\r
+ cld\r
+ pop cx\r
+ mov si, dx\r
+ mov di, a_obuf\r
+ pop bx\r
+ add bp, ax ; ax = 0 -> EOF\r
+ jc lc_3\r
+\r
+ push ax\r
+ test cl, cl\r
+ jz lc_6\r
+\r
+ cmp bx, byte 91 ; value in bit queue < 91?\r
+ sbb dx, dx\r
+ cmp cl, 8 ; less than 8 bits in queue?\r
+ sbb cx, cx\r
+ add bx, bx\r
+ and cx, dx\r
+ mov dx, a_obuf\r
+ mov ax, [bx + a_ltab]\r
+ inc cx\r
+ mov bx, 1\r
+ inc cx\r
+ stosw\r
+ mov ah, 0x40\r
+ int 0x21 ; write out 1 or 2 bytes\r
+lc_6:\r
+ retn ; exit program\r
+ld_0:\r
+ db 'ABCDEFGHIJKLM'\r
+ db 'NOPQRSTUVWXYZ'\r
+ db 'abcdefghijklm'\r
+ db 'nopqrstuvwxyz'\r
+ db '0123456789!#$'\r
+ db '%&()*+,./:;<='\r
+ db '>?@[]^_`{|}~"'\r
+\r
+\r
+a_stck equ ((lc_2 - $$) + 256) & 510\r
+a_ltab equ 48974\r
+a_obuf equ ((ld_0 - $$) + 257) & 510\r
+s_ibuf equ ((a_ltab - a_obuf - 2) << 4) / 29\r
+a_ibuf equ a_ltab - s_ibuf\r
--- /dev/null
+This is a compact 16-bit assembly implementation of the basE91 encoder for DOS.\r
+It encodes from standard input to standard output. Minimum system requirements:\r
+DOS 2.0, 8086 processor\r
+\r
+Example usage:\r
+\r
+ b91enc < file.bin > file.b91\r
+\r
+\r
+Assemble with NASM [http://nasm.sourceforge.net/]:\r
+\r
+ nasm -O2 -o b91enc.com b91enc.asm\r
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+#!/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
--- /dev/null
+Copyright (c) 2000-2006 Joachim Henke\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions are met:\r
+\r
+ - Redistributions of source code must retain the above copyright notice, this\r
+ list of conditions and the following disclaimer.\r
+ - Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+ - Neither the name of Joachim Henke nor the names of his contributors may be\r
+ used to endorse or promote products derived from this software without\r
+ specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
--- /dev/null
+Main-Class: b91cli
+Package-Title: basE91 command line tool
+Package-Version: 0.6.0
+Package-Vendor: Joachim Henke
--- /dev/null
+This is an implementation of the basE91 encoder and decoder in Java.\r
+\r
+Syntax:\r
+ java -jar base91.jar [OPTION] infile [outfile]\r
+\r
+Options:\r
+\r
+-d decode a basE91 encoded file;\r
+ all non-alphabet characters (such as newlines) are ignored\r
+\r
+-u leave encoder output unformatted;\r
+ i. e., disable line wrapping after 76 characters\r
+\r
+-h display short help and exit\r
+\r
+-V output version information and exit\r
+\r
+\r
+If no outfile is given for encoding, it defaults to `infile_b91.txt' (or to\r
+`infile.b91' with the `-u' switch).\r
+On decoding, the added file extension is removed to generate the name for\r
+outfile; otherwise, if infile hasn't a default extension, the decoded data is\r
+written to `infile.bin'.\r
+\r
+For further information visit the basE91 home page at\r
+http://base91.sourceforge.net/\r
--- /dev/null
+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.
--- /dev/null
+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 lentest
+
+.PHONY: all install check clean
+
+all: $(BIN)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $<
+
+base91: cli.o base91.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+lentest: lentest.o base91.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
--- /dev/null
+[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
--- /dev/null
+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:
+<?php
+ require_once 'base91.php';
+ $str = 'This is an encoded string';
+ echo base91_encode($str);
+?>
+
+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:
+<?php
+ require_once 'base91.php';
+ $str = 'nX,<:WRT%yV%!5:maref3+1RrUb64^M';
+ echo base91_decode($str);
+?>
+
+This example will produce:
+
+This is an encoded string
--- /dev/null
+<?php
+// Copyright (c) 2005-2006 Joachim Henke
+// http://base91.sourceforge.net/
+
+$b91_enctab = array(
+ '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', '!', '#', '$',
+ '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',
+ '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'
+);
+$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;
+}
+?>
--- /dev/null
+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 <j-o@users.sourceforge.net>
+
+
+* 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.
--- /dev/null
+.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 <j\-o@users.sourceforge.net>.
+.SH COPYRIGHT
+Copyright (c) 2000\-2006 Joachim Henke
+.SH "SEE ALSO"
+base64(1), uuencode(1)
+
+http://base91.sourceforge.net/
--- /dev/null
+/*
+ * 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;
+}
+
+/* return maximum length that an input of length i could encode to
+ * (this is a maximum, not a precise figure, because the actual
+ * size depends on the precise data */
+
+size_t basE91_encode_maxlen(size_t i /* must be < SIZE_T_MAX/8 */)
+{
+ size_t bits = i*8;
+ size_t pairs = bits / 13;
+ size_t leftover = bits % 13;
+ return 2*pairs + (leftover==0 ? 0 : leftover<=6 ? 1 : 2);
+}
+
+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;
+}
+
+/* return maximum length that an input of length i could decode to
+ * (this is a maximum, not a precise figure, because the actual
+ * size depends on the precise data */
+
+size_t basE91_decode_maxlen(size_t i /* must be < SIZE_T_MAX/7 */)
+{
+ size_t pairs = i / 2;
+ size_t bits = pairs * 14;
+ size_t bytes = bits / 8;
+ size_t leftover = i % 2;
+ return bytes + !!leftover;
+}
--- /dev/null
+/*
+ * 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 <stddef.h>
+
+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_encode_maxlen(size_t /* must be < SIZE_T_MAX/8 */);
+
+size_t basE91_decode(struct basE91 *, const void *, size_t, void *);
+
+size_t basE91_decode_end(struct basE91 *, void *);
+
+size_t basE91_decode_maxlen(size_t /* must be < SIZE_T_MAX/7 */);
+
+#endif /* base91.h */
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+#include <getopt.h>
+#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);
+ const char *ifile = "from standard input";
+ const 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;
+}
--- /dev/null
+/*
+ * basE91 length calculation test
+ *
+ * Copyright (c) 2019 Ian Jackson
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "base91.h"
+
+static size_t upto = (14*16 + 14 + 16)*2;
+
+static int do_test(int do_do, int fill, const char *what,
+ size_t f(struct basE91 *, const void *, size_t, void *),
+ size_t f_end(struct basE91 *, void *),
+ size_t f_maxlen(size_t)
+ )
+{
+ struct basE91 b;
+ size_t i, o, exp;
+ int bad = 0;
+ char ibuf[upto];
+ char obuf[upto*2+100]; /* in case we have bugs */
+
+ memset(ibuf,fill,upto);
+
+ if (!do_do) {
+ printf("%s: skipping\n",what);
+ return 0;
+ }
+
+ for (i=0; i<upto; i++) {
+ basE91_init(&b);
+ o = f(&b, ibuf, i, obuf);
+ o += f_end(&b, obuf+o);
+
+ exp = f_maxlen(i);
+ if (o == exp) continue;
+
+ bad = 1;
+ fprintf(stderr,"%s: i=%lu o=%lu expected=%lu\n",
+ what, (unsigned long)i, (unsigned long)o, (unsigned long)exp);
+ }
+ return bad;
+}
+
+int main(int argc, const char **argv) {
+ int do_encode=1, do_decode=1, bad=0;
+
+ if (argc>=2) {
+ do_encode = !!strchr(argv[1],'e');
+ do_decode = !!strchr(argv[1],'d');
+ }
+ if (argc>=3) {
+ upto = atoi(argv[2]);
+ }
+
+#define MAYBE_DO_TEST(ed, fill) \
+ (bad |= do_test(do_##ed, (fill), #ed, \
+ basE91_##ed, basE91_##ed##_end, basE91_##ed##_maxlen))
+ MAYBE_DO_TEST(encode, 0xff);
+ MAYBE_DO_TEST(decode, 'A');
+
+ if (bad) exit(8);
+ printf("ok\n");
+ exit(0);
+}
--- /dev/null
+SHELL = /bin/sh
+
+.PHONY: all clean
+
+all:
+ ln -sf ../base91 b91enc
+ ln -sf ../base91 b91dec
+ ln -sf ../lentest .
+ $(SHELL) test.sh
+
+clean:
+ -rm -f b91??c *.b91 *.dat core
--- /dev/null
+fail_exit()
+{
+ echo 'FAILED!'
+ exit 1
+}
+
+T='--------------------------------------+'
+
+./b91enc --version || fail_exit
+echo -n '
+
+extracting test files...'
+echo '?/9f4iG0)z4jY;<$:B$AvWAAoB:CgALvDCeR+t<vs?JIdPSQ;L5lB3S' | ./b91dec | bunzip2 > bit0.dat && \
+echo '?/9f4iG0)z4jZgv|?AUYRAgA%AAAUA:y5L9LcoHE8HJI_yGIJ>T' | ./b91dec | bunzip2 > bit1.dat && \
+echo '71kS$5F/VZC0+Zw,c%df~>T1XkEvl{weS1NQ@@<EsB7?HV[3U(PhH}H)<LB9_E.4R)1I9W;Ce";rDlheie/
+X*Jh)bS+Jj]iu8V}b61nw32m:"$2@F)s(3LV,n5M?D=NZ9cM,9dV2t_eN#CVg4n@?Zx@FuNG2z|4iLzZvXbx*v_4M
+.ij4Cu=x~WzlpmRKXl3%kWqxx{wo38|Skh/q&;}D#~|Ng3$Gaw>3Gd*`P2p~<hXL_x?V:^0wcZ3x/LpEtP<]gaCm6
+O]D:}u%LONIl2iohu8h6ZXN+3ZS*w"r:8[U?B{?}mt@+<W24O"FA_#^(L$:Tg}#BYwqZc&uT_o,BSG4boOe]ij8fV
+8f/]aBW37mJIfH7uE=l)_y}F*^UA_L9,XPP<jSCN9y4ua|2jhD]E$}>)^4>yP{Y9MFo.Q2=Mmsk:"lhR%87Ey_GRP
+7hn_L73QVn>5CK0{6eHmBBtzP05[`PG3*"+n(bE$S";_b^gU5D87O,QjqW<sS}3&CyTDB~hH,oTOV/My7[vP&mg=W
+sDWjXHh2+q,pmh{AK4U!#n6@VfZFA!]p7E;_gWX_Q#!>3wVc(_T8_:O{8P$9~{n7"SiU;Ca{w_;HB6L&u2W8M>ScI
+aP#E.:novN/#Mk$STQeM^dSp5~JKkb3[t<MeaHgV_*vy=W#0B$3pH6/;q9]C<v=}2IewY6{PigoQ"b[:7+;!k8kv[
+!M@y}I~m%fm&x?S5]CDM&>5_*3q&V/Z7aVdFP<K[R"RkdOfN/.8>J#P&TR3#`W+;&GpWk9CHq%R|fV~(K:g6_Du~m
+j7S?;hnI$xFkGTDRJSJ#NNu_;(]ud#<HI7isnSR@,6ftg8D;$+[j8}mr7lrAijly3cxX7+l3[)@.c7Vk`#kEB,g,P
+>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(<w
+RDd6[tY/gsu(CNd#j*do&Id|iCGCBG$FD4(JUlb"~O8E`."F<SdvvP;Xfn?V:uVP,I(XD|@)5KVNwx2k/`&vyXrnl
+Ots<a+&YHAL[Wyn,Zc*r3&.=8w~+PIs}.bioO`|D,52ku,daF"WA&nT)!"j&!EiNJ{y.%`Ba3R.f,#rF4qH07uekh
+qd"o]wvyXzrC_i#pC9+KWV5Nh},s^3|R0EV4g?#KJvp^V_.w$GAXf0,SU#=Z)ugj4k@T&A$/JVzgkwqJX9lx,YuFf
+1whB6~5[P^DGQN@}nhPX>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`=r0<Ew]RDY0qgDvOBKh?sKz=uxOY8Tv{
+c4;c)QQ3*ilu6I?W$}5M[K1UA29,xzD;<;%y*=b$X8[Z^Cb~QPagi;{[sEk(Ttm3.@Gjm%@ii*Cl{&>eo&uZFyq*`
+dg.h"YJiW)t5BaO;?liP7Y|)o|]9KwM`rZO1p#<WohA$KEPZU3rm"!_WNwMg[Yj{9MbgNFkygUc4rb*:k:z;)qV+g
+W]t76>}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},xK<T
+VZa!xDsn66YUg~,En93Xg9u2c~?o~=,#$e]~KHG&tBM)bOvSN:0GHsZ|u$6523G(6wxlo_eqx!<CzIScE~pC+2;1W
+:G^D7,k+do4Wr+4j4|Q:vj]c?J+Wz:Lyn<+W)8]>nvFBHnD&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 "
+maxlength tests:"
+./lentest && echo PASSED || fail_exit
+
+echo '
+================
+all tests passed
+================
+'