Files to add Deflater and DeflaterOutputStream to java.util.zip for

avian
This commit is contained in:
jent 2009-12-04 12:01:31 -07:00
parent 60333c88f5
commit 99a1c12682
5 changed files with 300 additions and 0 deletions

View File

@ -80,3 +80,69 @@ Java_java_util_zip_Inflater_inflate
e->SetIntArrayRegion(results, 0, 3, resultArray); e->SetIntArrayRegion(results, 0, 3, resultArray);
} }
extern "C" JNIEXPORT jlong JNICALL
Java_java_util_zip_Deflater_make
(JNIEnv* e, jclass, jboolean nowrap, jint level)
{
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
memset(s, 0, sizeof(z_stream));
int r = deflateInit2(s, level, (nowrap ? -15 : 15));
if (r != Z_OK) {
free(s);
throwNew(e, "java/lang/RuntimeException", zError(r));
return 0;
}
return reinterpret_cast<jlong>(s);
}
extern "C" JNIEXPORT void JNICALL
Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer)
{
z_stream* s = reinterpret_cast<z_stream*>(peer);
deflateEnd(s);
free(s);
}
extern "C" JNIEXPORT void JNICALL
Java_java_util_zip_Deflater_deflate
(JNIEnv* e, jclass, jlong peer,
jbyteArray input, jint inputOffset, jint inputLength,
jbyteArray output, jint outputOffset, jint outputLength,
jintArray results)
{
z_stream* s = reinterpret_cast<z_stream*>(peer);
jbyte* in = static_cast<jbyte*>(malloc(inputLength));
if (in == 0) {
throwNew(e, "java/lang/OutOfMemoryError", 0);
return;
}
jbyte* out = static_cast<jbyte*>(malloc(outputLength));
if (out == 0) {
free(in);
throwNew(e, "java/lang/OutOfMemoryError", 0);
return;
}
e->GetByteArrayRegion(input, inputOffset, inputLength, in);
s->next_in = reinterpret_cast<Bytef*>(in);
s->avail_in = inputLength;
s->next_out = reinterpret_cast<Bytef*>(out);
s->avail_out = outputLength;
int r = deflate(s, Z_SYNC_FLUSH);
jint resultArray[3]
= { r, inputLength - s->avail_in, outputLength - s->avail_out };
free(in);
e->SetByteArrayRegion(output, outputOffset, resultArray[2], out);
free(out);
e->SetIntArrayRegion(results, 0, 3, resultArray);
}

View File

@ -0,0 +1,149 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.util.zip;
public class Deflater {
private static final int DEFAULT_LEVEL = 6; // default compression level (6 is default for gzip)
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;
private final boolean nowrap;
public Deflater(boolean nowrap) {
this.nowrap = nowrap;
peer = make(nowrap, DEFAULT_LEVEL);
}
public Deflater() {
this(false);
}
private void check() {
if (peer == 0) {
throw new IllegalStateException();
}
}
private static native long make(boolean nowrap, int level);
public boolean finished() {
return finished;
}
public boolean needsDictionary() {
return needDictionary;
}
public boolean needsInput() {
return getRemaining() == 0;
}
public int getRemaining() {
return length;
}
public void setLevel(int level) throws IllegalArgumentException {
if (level < 0 || level > 9) {
throw new IllegalArgumentException("Valid compression levels are 0-9");
}
dispose(peer);
peer = make(nowrap, level);
}
public void setInput(byte[] input) {
setInput(input, 0, input.length);
}
public void setInput(byte[] input, int offset, int length) {
this.input = input;
this.offset = offset;
this.length = length;
}
public void reset() {
dispose();
peer = make(nowrap, DEFAULT_LEVEL);
input = null;
offset = length = 0;
needDictionary = finished = false;
}
public int deflate(byte[] output) throws DataFormatException {
return deflate(output, 0, output.length);
}
public int deflate(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];
deflate(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 deflate
(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

@ -0,0 +1,75 @@
/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package java.util.zip;
import java.io.OutputStream;
import java.io.IOException;
public class DeflaterOutputStream extends OutputStream {
private final OutputStream out;
private final Deflater deflater;
private final byte[] buffer;
public DeflaterOutputStream(OutputStream out, Deflater deflater, int bufferSize)
{
this.out = out;
this.deflater = deflater;
this.buffer = new byte[bufferSize];
}
public DeflaterOutputStream(OutputStream out, Deflater deflater) {
this(out, deflater, 4 * 1024);
}
public DeflaterOutputStream(OutputStream out) {
this(out, new Deflater());
}
public void write(int b) throws IOException {
byte[] buffer = new byte[1];
buffer[0] = (byte)(b & 0xff);
write(buffer, 0, 1);
}
public void write(byte[] b, int offset, int length) throws IOException {
// error condition checking
if (deflater.finished()) {
throw new IOException("Already at end of stream");
} else if (offset < 0) {
throw new IndexOutOfBoundsException("Offset can't be less than zero");
} else if (length < 0) {
throw new IndexOutOfBoundsException("Length can't be less than zero");
} else if (b.length - (offset + length) < 0) {
throw new IndexOutOfBoundsException("Offset + Length is larger than the input byte array");
} else if (length == 0) {
return;
}
for (int i = 0; i < length; i+= buffer.length) {
deflater.setInput(b, offset + i, Math.min(buffer.length, length - i));
while (deflater.getRemaining() > 0) {
try {
int len = deflater.deflate(buffer, 0, buffer.length);
if (len > 0) {
out.write(buffer, 0, len);
}
} catch (DataFormatException e) {
e.printStackTrace();
}
}
}
}
public void close() throws IOException {
out.close();
deflater.dispose();
}
}

View File

@ -59,6 +59,10 @@ public class Inflater {
public int getRemaining() { public int getRemaining() {
return length; return length;
} }
public void setInput(byte[] input) {
setInput(input, 0, input.length);
}
public void setInput(byte[] input, int offset, int length) { public void setInput(byte[] input, int offset, int length) {
this.input = input; this.input = input;

View File

@ -15,3 +15,9 @@
#define inflateInit2(strm, windowBits) \ #define inflateInit2(strm, windowBits) \
inflateInit2_((strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream))) inflateInit2_((strm), (windowBits), ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
#endif #endif
#ifdef deflateInit2
#undef deflateInit2
#define deflateInit2(strm, level, windowBits) \
deflateInit2_((strm), (level), Z_DEFLATED, (windowBits), 8, Z_DEFAULT_STRATEGY, ZLIB_VERSION, static_cast<int>(sizeof(z_stream)))
#endif