package net.solarnetwork.io;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* The ASCII85InputStream encodes binary data as ASCII base-85 encoding. The
* exact definition of ASCII base-85 encoding can be found in the PostScript
* Language Reference (3rd ed.) chapter 3.13.3.
*
* <p>
* This adaptation from the original source omits the ASCII85 "armor" {@code <~}
* and {@code ~>}.
* </p>
*
* @author Mark Donszelmann
* @version 1.4 2003/04/13 05:34:45
*/
public class ASCII85OutputStream extends FilterOutputStream {
public final static int MAX_CHARS_PER_LINE = 80;
public static long a85p1 = 85;
public static long a85p2 = a85p1 * a85p1;
public static long a85p3 = a85p2 * a85p1;
public static long a85p4 = a85p3 * a85p1;
private boolean end;
private int characters;
private final int b[] = new int[4];
private int bIndex;
private final int c[] = new int[5];
public ASCII85OutputStream(OutputStream out) {
super(out);
characters = MAX_CHARS_PER_LINE;
end = false;
bIndex = 0;
}
@Override
public void write(int a) throws IOException {
b[bIndex] = a & 0x00FF;
bIndex++;
if ( bIndex >= b.length ) {
writeTuple();
bIndex = 0;
}
}
public void finish() throws IOException {
if ( !end ) {
end = true;
if ( bIndex > 0 ) {
writeTuple();
}
flush();
}
}
@Override
public void close() throws IOException {
finish();
super.close();
}
private void writeTuple() throws IOException {
// fill the rest
for ( int i = bIndex; i < b.length; i++ ) {
b[i] = 0;
}
// convert
long d = ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) & 0x00000000FFFFFFFFL;
c[0] = (int) (d / a85p4 + '!');
d = d % a85p4;
c[1] = (int) (d / a85p3 + '!');
d = d % a85p3;
c[2] = (int) (d / a85p2 + '!');
d = d % a85p2;
c[3] = (int) (d / a85p1 + '!');
c[4] = (int) (d % a85p1 + '!');
// convert !!!!! to z
if ( (bIndex >= b.length) && (c[0] == '!') && (c[1] == '!') && (c[2] == '!') && (c[3] == '!')
&& (c[4] == '!') ) {
writeChar('z');
} else {
for ( int i = 0; i < bIndex + 1; i++ ) {
writeChar(c[i]);
}
}
}
private void writeChar(int b) throws IOException {
if ( characters == 0 ) {
characters = MAX_CHARS_PER_LINE;
super.write('\n');
}
characters--;
super.write(b);
}
}