mirror of
https://github.com/corda/corda.git
synced 2025-02-27 03:27:34 +00:00
implement Inflater and InflaterInputStream
This commit is contained in:
parent
8af76b0da6
commit
923c4661e8
75
classpath/java-util-zip.cpp
Normal file
75
classpath/java-util-zip.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni-util.h"
|
||||
|
||||
#undef JNIEXPORT
|
||||
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_Inflater_make
|
||||
(JNIEnv* e, jclass, jboolean nowrap)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(malloc(sizeof(z_stream)));
|
||||
memset(s, 0, sizeof(z_stream));
|
||||
|
||||
int r = inflateInit2(s, (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_Inflater_dispose(JNIEnv*, jclass, jlong peer)
|
||||
{
|
||||
z_stream* s = reinterpret_cast<z_stream*>(peer);
|
||||
inflateEnd(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_Inflater_inflate
|
||||
(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 = inflate(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);
|
||||
}
|
11
classpath/java/util/zip/DataFormatException.java
Normal file
11
classpath/java/util/zip/DataFormatException.java
Normal file
@ -0,0 +1,11 @@
|
||||
package java.util.zip;
|
||||
|
||||
public class DataFormatException extends Exception {
|
||||
public DataFormatException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public DataFormatException() {
|
||||
super();
|
||||
}
|
||||
}
|
110
classpath/java/util/zip/Inflater.java
Normal file
110
classpath/java/util/zip/Inflater.java
Normal 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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user