implement Inflater and InflaterInputStream

This commit is contained in:
Joel Dice
2007-09-17 16:15:16 -06:00
parent 8af76b0da6
commit 923c4661e8
4 changed files with 243 additions and 2 deletions

View File

@ -0,0 +1,11 @@
package java.util.zip;
public class DataFormatException extends Exception {
public DataFormatException(String s) {
super(s);
}
public DataFormatException() {
super();
}
}

View File

@ -0,0 +1,110 @@
package java.util.zip;
public class Inflater {
private static final int Z_OK = 0;
private static final int Z_STREAM_END = 1;
private static final int Z_NEED_DICT = 2;
static {
System.loadLibrary("natives");
}
private long peer;
private byte[] input;
private int offset;
private int length;
private boolean needDictionary;
private boolean finished;
public Inflater(boolean nowrap) {
peer = make(nowrap);
}
public Inflater() {
this(false);
}
private void check() {
if (peer == 0) {
throw new IllegalStateException();
}
}
private static native long make(boolean nowrap);
public boolean finished() {
return finished;
}
public boolean needsDictionary() {
return needDictionary;
}
public boolean needsInput() {
return getRemaining() == 0;
}
public int getRemaining() {
return length;
}
public void setInput(byte[] input, int offset, int length) {
this.input = input;
this.offset = offset;
this.length = length;
}
public int inflate(byte[] output, int offset, int length)
throws DataFormatException
{
final int zlibResult = 0;
final int inputCount = 1;
final int outputCount = 2;
if (peer == 0) {
throw new IllegalStateException();
}
if (input == null || output == null) {
throw new NullPointerException();
}
int[] results = new int[3];
inflate(peer, input, this.offset, this.length,
output, offset, length, results);
if (results[zlibResult] < 0) {
throw new DataFormatException();
}
switch (results[zlibResult]) {
case Z_NEED_DICT:
needDictionary = true;
break;
case Z_STREAM_END:
finished = true;
break;
}
this.offset += results[inputCount];
this.length -= results[inputCount];
return results[outputCount];
}
private static native void inflate
(long peer,
byte[] input, int inputOffset, int inputLength,
byte[] output, int outputOffset, int outputLength,
int[] results);
public void dispose() {
if (peer != 0) {
dispose(peer);
peer = 0;
}
}
private static native void dispose(long peer);
}

View File

@ -2,19 +2,64 @@ package java.util.zip;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
public class InflaterInputStream extends InputStream {
private final InputStream in;
private final Inflater inflater;
private final byte[] buffer;
public InflaterInputStream(InputStream in, Inflater inflater, int bufferSize)
{
this.in = in;
this.inflater = inflater;
this.buffer = new byte[bufferSize];
}
public InflaterInputStream(InputStream in, Inflater inflater) {
this(in, inflater, 4 * 1024);
}
public InflaterInputStream(InputStream in) {
this.in = in;
this(in, new Inflater());
}
public int read() throws IOException {
throw new IOException("not implemented");
byte[] buffer = new byte[1];
int c = read(buffer);
return (c < 0 ? c : (buffer[0] & 0xFF));
}
public int read(byte[] b, int offset, int length) throws IOException {
if (inflater.finished()) {
return -1;
}
while (true) {
if (inflater.needsInput()) {
int count = in.read(buffer);
if (count > 0) {
inflater.setInput(buffer, 0, count);
} else {
throw new EOFException();
}
}
try {
int count = inflater.inflate(b, offset, length);
if (count > 0) {
return count;
} else if (inflater.needsDictionary()) {
throw new IOException("missing dictionary");
}
} catch (DataFormatException e) {
throw new IOException(e);
}
}
}
public void close() throws IOException {
in.close();
inflater.dispose();
}
}