// Copyright 2001, FreeHEP.
package org.freehep.util.io;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* The ASCII85InputStream decodes ASCII base-85 encoded data. The exact
* definition of ASCII base-85 encoding can be found in the PostScript Language
* Reference (3rd ed.) chapter 3.13.3.
*
* IMPORTANT: inherits from InputStream rather than FilterInputStream so that
* the correct read(byte[], int, int) method is used.
*
* @author Mark Donszelmann
* @version $Id: ASCII85InputStream.java 8584 2006-08-10 23:06:37Z duns $
*/
public class ASCII85InputStream extends InputStream implements ASCII85 {
private boolean endReached;
private int b[] = new int[4];
private int bIndex;
private int bLength;
private int c[] = new int[5];
private int lineNo;
private int prev;
private InputStream in;
/**
* Create an ASCII85 Input Stream from given stream.
*
* @param input input to use
*/
public ASCII85InputStream(InputStream input) {
super();
in = input;
bIndex = 0;
bLength = 0;
endReached = false;
prev = -1;
lineNo = 1;
}
public int read() throws IOException {
if (bIndex >= bLength) {
if (endReached)
return -1;
bLength = readTuple();
if (bLength < 0)
return -1;
bIndex = 0;
}
int a = b[bIndex];
bIndex++;
return a;
}
/**
* @return current line number
*/
public int getLineNo() {
return lineNo;
}
private int readTuple() throws IOException, EncodingException {
int cIndex = 0;
int ch = -1;
while ((!endReached) && (cIndex < 5)) {
prev = ch;
ch = in.read();
switch (ch) {
case -1:
throw new EncodingException(
"missing '~>' at end of ASCII85 stream");
case 'z':
b[0] = b[1] = b[2] = b[3] = '!';
return 4;
case '~':
if (in.read() != '>')
throw new EncodingException("Invalid ASCII85 EOD");
endReached = true;
break;
case '\r':
lineNo++;
break;
case '\n':
if (prev != '\r') {
lineNo++;
}
break;
case ' ':
case '\t':
case '\f':
case 0:
// ignored
break;
default:
c[cIndex] = ch;
cIndex++;
break;
}
}
if (cIndex > 0) {
// fill the rest
for (int i = 0; i < c.length; i++) {
if (i >= cIndex) {
c[i] = '!';
} else {
c[i] -= '!';
}
}
// convert
long d = ((c[0] * a85p4) + (c[1] * a85p3) + (c[2] * a85p2)
+ (c[3] * a85p1) + c[4]) & 0x00000000FFFFFFFFL;
b[0] = (int) ((d >> 24) & 0x00FF);
b[1] = (int) ((d >> 16) & 0x00FF);
b[2] = (int) ((d >> 8) & 0x00FF);
b[3] = (int) (d & 0x00FF);
}
return cIndex - 1;
}
/**
* Print out ASCII85 of a file
*
* @param args filename
* @throws Exception when file does not exist
*/
public static void main(String[] args) throws Exception {
if (args.length < 1) {
System.err.println("Usage: ASCII85InputStream filename");
System.exit(1);
}
ASCII85InputStream in = new ASCII85InputStream(new FileInputStream(args[0]));
int b = in.read();
while (b != -1) {
System.out.write(b);
b = in.read();
}
in.close();
System.out.flush();
}
}