aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/util
diff options
context:
space:
mode:
authorTom Tromey <tromey@cygnus.com>1999-05-18 15:33:03 +0000
committerTom Tromey <tromey@gcc.gnu.org>1999-05-18 15:33:03 +0000
commit0ffac8322f8825c0d696d9c700b0d0f1a395d11a (patch)
treec538fe74824c64ba74944a357c354f0c77e93be5 /libjava/java/util
parent5a9e5c6fb6c140bd80a2986f1d537a250a62ea59 (diff)
downloadgcc-0ffac8322f8825c0d696d9c700b0d0f1a395d11a.zip
gcc-0ffac8322f8825c0d696d9c700b0d0f1a395d11a.tar.gz
gcc-0ffac8322f8825c0d696d9c700b0d0f1a395d11a.tar.bz2
ZipOutputStream.java (level): Initial value is Deflater.DEFAULT_COMPRESSION.
* java/util/zip/ZipOutputStream.java (level): Initial value is Deflater.DEFAULT_COMPRESSION. (close): New method. (closeEntry): Likewise. (finish): Likewise. (put_version): Likewise. (write_entry): Likewise. (put2, put4): Now return `int'. (comment): Default to empty string. (bytes_written): New instance variable. (chain): Likewise. * java/util/zip/ZipEntry.java (setComment): Limit length of comment string. (setCrc): Check CRC validity. (setExtra): Check argument validity. (setMethod): Likewise. (setSize): Likewise. (ZipEntry): Likewise. * include/javaprims.h: Updated namespace declarations. * Makefile.in: Rebuilt. * Makefile.am (ordinary_java_source_files): Mention new files. (nat_source_files): Likewise. * java/util/zip/ZipFile.java (readu2): Throw ZipException, not EOFException. (read4): Likewise. (getInputStream): Handle compressed entries. * java/util/zip/GZIPOutputStream.java: New file. * java/util/zip/GZIPInputStream.java: New file. * java/util/zip/DataFormatException.java: New file. * java/util/zip/CheckedInputStream.java: New file. * java/util/zip/CheckedOutputStream.java: New file. * java/util/zip/InflaterInputStream.java: Implemented. * java/util/zip/natInflater.cc: New file. * java/util/zip/Deflater.java: Implemented. * java/util/zip/natDeflater.cc: New file. * java/util/zip/DeflaterOutputStream.java: Implemented. * java/util/zip/ZipInputStream.java (closeZipEntry): Throw ZipException, not IOException. * java/util/zip/ZipFile.java (readDirectory): Throw ZipException, not IOException. From-SVN: r26996
Diffstat (limited to 'libjava/java/util')
-rw-r--r--libjava/java/util/zip/CheckedInputStream.java80
-rw-r--r--libjava/java/util/zip/CheckedOutputStream.java54
-rw-r--r--libjava/java/util/zip/DataFormatException.java33
-rw-r--r--libjava/java/util/zip/Deflater.java119
-rw-r--r--libjava/java/util/zip/DeflaterOutputStream.java65
-rw-r--r--libjava/java/util/zip/GZIPInputStream.java154
-rw-r--r--libjava/java/util/zip/GZIPOutputStream.java88
-rw-r--r--libjava/java/util/zip/Inflater.java101
-rw-r--r--libjava/java/util/zip/InflaterInputStream.java90
-rw-r--r--libjava/java/util/zip/ZipEntry.java44
-rw-r--r--libjava/java/util/zip/ZipFile.java34
-rw-r--r--libjava/java/util/zip/ZipInputStream.java4
-rw-r--r--libjava/java/util/zip/ZipOutputStream.java263
-rw-r--r--libjava/java/util/zip/natDeflater.cc209
-rw-r--r--libjava/java/util/zip/natInflater.cc202
15 files changed, 1472 insertions, 68 deletions
diff --git a/libjava/java/util/zip/CheckedInputStream.java b/libjava/java/util/zip/CheckedInputStream.java
new file mode 100644
index 0000000..a6a9058
--- /dev/null
+++ b/libjava/java/util/zip/CheckedInputStream.java
@@ -0,0 +1,80 @@
+// CheckedInputStream.java - Compute checksum of data being read.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util.zip;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class CheckedInputStream extends FilterInputStream
+{
+ public CheckedInputStream (InputStream in, Checksum sum)
+ {
+ super (in);
+ this.sum = sum;
+ }
+
+ public Checksum getChecksum ()
+ {
+ return sum;
+ }
+
+ public int read () throws IOException
+ {
+ int x = in.read();
+ if (x != -1)
+ sum.update(x);
+ return x;
+ }
+
+ public int read (byte[] buf, int off, int len) throws IOException
+ {
+ int r = in.read(buf, off, len);
+ if (r != -1)
+ sum.update(buf, off, r);
+ return r;
+ }
+
+ public long skip (long n) throws IOException
+ {
+ if (n == 0)
+ return 0;
+
+ int min = (int) Math.min(n, 1024);
+ byte[] buf = new byte[min];
+
+ long s = 0;
+ while (n > 0)
+ {
+ int r = in.read(buf, 0, min);
+ if (r == -1)
+ break;
+ n -= r;
+ s += r;
+ sum.update(buf, 0, r);
+ }
+
+ return s;
+ }
+
+ // The checksum object.
+ private Checksum sum;
+}
diff --git a/libjava/java/util/zip/CheckedOutputStream.java b/libjava/java/util/zip/CheckedOutputStream.java
new file mode 100644
index 0000000..30dbc73
--- /dev/null
+++ b/libjava/java/util/zip/CheckedOutputStream.java
@@ -0,0 +1,54 @@
+// CheckedOutputStream.java - Compute checksum of data being written.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util.zip;
+
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class CheckedOutputStream extends FilterOutputStream
+{
+ public CheckedOutputStream (OutputStream out, Checksum cksum)
+ {
+ super (out);
+ this.sum = cksum;
+ }
+
+ public Checksum getChecksum ()
+ {
+ return sum;
+ }
+
+ public void write (int bval) throws IOException
+ {
+ out.write(bval);
+ sum.update(bval);
+ }
+
+ public void write (byte[] buf, int off, int len) throws IOException
+ {
+ out.write(buf, off, len);
+ sum.update(buf, off, len);
+ }
+
+ // The checksum object.
+ private Checksum sum;
+}
diff --git a/libjava/java/util/zip/DataFormatException.java b/libjava/java/util/zip/DataFormatException.java
new file mode 100644
index 0000000..258f47f
--- /dev/null
+++ b/libjava/java/util/zip/DataFormatException.java
@@ -0,0 +1,33 @@
+// DataFormatException.java
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libjava.
+
+This software is copyrighted work licensed under the terms of the
+Libjava License. Please consult the file "LIBJAVA_LICENSE" for
+details. */
+
+package java.util.zip;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification.
+ * Believed complete and correct.
+ */
+
+public class DataFormatException extends java.io.IOException
+{
+ public DataFormatException ()
+ {
+ super();
+ }
+
+ public DataFormatException (String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/java/util/zip/Deflater.java b/libjava/java/util/zip/Deflater.java
index 81312e2..70855c5 100644
--- a/libjava/java/util/zip/Deflater.java
+++ b/libjava/java/util/zip/Deflater.java
@@ -1,3 +1,5 @@
+// Deflater.java - Compress a data stream.
+
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@@ -8,6 +10,123 @@ details. */
package java.util.zip;
+import gnu.gcj.RawData;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
public class Deflater
{
+ public static final int BEST_COMPRESSION = 9;
+ public static final int BEST_SPEED = 1;
+ public static final int DEFAULT_COMPRESSION = -1;
+ public static final int NO_COMPRESSION = 0;
+
+ public static final int DEFAULT_STRATEGY = 0;
+ public static final int FILTERED = 1;
+ public static final int HUFFMAN_ONLY = 2;
+
+ public static final int DEFLATED = 8;
+
+ public int deflate (byte[] buf)
+ {
+ return deflate (buf, 0, buf.length);
+ }
+
+ public native int deflate (byte[] buf, int off, int len);
+ public native void init (int level, boolean noHeader);
+ public native void update ();
+
+ public Deflater ()
+ {
+ this (DEFAULT_COMPRESSION, false);
+ }
+
+ public Deflater (int lvl)
+ {
+ this (lvl, false);
+ }
+
+ public Deflater (int lvl, boolean noHeader)
+ {
+ this.strategy = DEFAULT_STRATEGY;
+ init (lvl, noHeader);
+ setLevel (lvl);
+ }
+
+ public native void end ();
+
+ public void finalize ()
+ {
+ end ();
+ }
+
+ public native void finish ();
+
+ public synchronized boolean finished ()
+ {
+ return is_finished;
+ }
+
+ public native int getAdler ();
+ public native int getTotalIn ();
+ public native int getTotalOut ();
+ public native boolean needsInput ();
+ public native void reset ();
+
+ public void setDictionary (byte[] buf)
+ {
+ setDictionary (buf, 0, buf.length);
+ }
+
+ public native void setDictionary (byte[] buf, int off, int len);
+
+ public void setInput (byte[] buf)
+ {
+ setInput (buf, 0, buf.length);
+ }
+
+ public native void setInput (byte[] buf, int off, int len);
+
+ public synchronized void setLevel (int lvl)
+ {
+ if (lvl != -1 && (lvl < 0 || lvl > 9))
+ throw new IllegalArgumentException ();
+ level = (lvl == -1) ? 6 : lvl;
+ update ();
+ }
+
+ public synchronized void setStrategy (int stgy)
+ {
+ if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
+ && stgy != HUFFMAN_ONLY)
+ throw new IllegalArgumentException ();
+ strategy = stgy;
+ update ();
+ }
+
+ // Compression level.
+ private int level;
+
+ // Compression strategy.
+ private int strategy;
+
+ // The zlib stream.
+ private RawData zstream;
+
+ // True if finished.
+ private boolean is_finished;
+
+ // Total number of bytes made available at last setInput.
+ private int last_input_count;
+
+ // `Flush' flag to pass to next call to deflate.
+ private int flush_flag;
}
diff --git a/libjava/java/util/zip/DeflaterOutputStream.java b/libjava/java/util/zip/DeflaterOutputStream.java
index 4f0b8b4..ce5ae23 100644
--- a/libjava/java/util/zip/DeflaterOutputStream.java
+++ b/libjava/java/util/zip/DeflaterOutputStream.java
@@ -1,3 +1,5 @@
+// DeflaterOutputStream.java - Output filter for compressing.
+
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@@ -7,40 +9,79 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
-import java.io.*;
-/** JUST AN INCOMPLETE STUB! */
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
public class DeflaterOutputStream extends FilterOutputStream
{
- protected byte[] buf;
+ public void close () throws IOException
+ {
+ finish ();
+ out.close();
+ }
- protected Deflater def;
+ protected void deflate () throws IOException
+ {
+ while (true)
+ {
+ int len = def.deflate(buf, 0, buf.length);
+ if (len == 0 || len == -1)
+ break;
+ out.write(buf, 0, len);
+ }
+ }
- public DeflaterOutputStream(OutputStream out)
+ public DeflaterOutputStream (OutputStream out)
{
- this(out, null, 512);
+ this (out, new Deflater (), 512);
}
- public DeflaterOutputStream(OutputStream out, Deflater defl)
+ public DeflaterOutputStream (OutputStream out, Deflater defl)
{
- this(out, defl, 512);
+ this (out, defl, 512);
}
public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
{
- super(out);
+ super (out);
buf = new byte[bufsize];
def = defl;
}
public void finish () throws IOException
{
+ def.finish();
+ deflate ();
}
- public void close () throws IOException
+ public void write (int bval) throws IOException
{
- finish();
- out.close();
+ byte[] b = new byte[1];
+ b[0] = (byte) bval;
+ write (b, 0, 1);
+ }
+
+ public void write (byte[] buf, int off, int len) throws IOException
+ {
+ def.setInput (buf, off, len);
+ deflate ();
}
+
+ // The retrieval buffer.
+ protected byte[] buf;
+
+ // Deflater used to compress data.
+ protected Deflater def;
}
diff --git a/libjava/java/util/zip/GZIPInputStream.java b/libjava/java/util/zip/GZIPInputStream.java
new file mode 100644
index 0000000..109ee82
--- /dev/null
+++ b/libjava/java/util/zip/GZIPInputStream.java
@@ -0,0 +1,154 @@
+// GZIPInputStream.java - Input tiler for reading gzip file.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util.zip;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class GZIPInputStream extends InflaterInputStream
+{
+ public static final int GZIP_MAGIC = 0x8b1f;
+
+ public void close () throws IOException
+ {
+ // Nothing to do here.
+ super.close();
+ }
+
+ public GZIPInputStream (InputStream istream) throws IOException
+ {
+ this (istream, 512);
+ }
+
+ private final int eof_read () throws IOException
+ {
+ int r = in.read();
+ if (r == -1)
+ throw new ZipException ("gzip header corrupted");
+ return r & 0xff;
+ }
+
+ public GZIPInputStream (InputStream istream, int readsize)
+ throws IOException
+ {
+ super (istream, new Inflater (true), readsize);
+
+ // NOTE: header reading code taken from zlib's gzio.c.
+
+ // Read the magic number.
+ int magic = eof_read () | (eof_read () << 8);
+ if (magic != GZIP_MAGIC)
+ throw new ZipException ("gzip header corrupted");
+
+ int method = eof_read ();
+ int flags = eof_read ();
+ // Test from zlib.
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0)
+ throw new ZipException ("gzip header corrupted");
+
+ // Discard time, xflags, OS code.
+ for (int i = 0; i < 6; ++i)
+ eof_read ();
+
+ // Skip the extra field.
+ if ((flags & EXTRA_FIELD) != 0)
+ {
+ int len = eof_read () | (eof_read () << 8);
+ while (len-- != 0)
+ eof_read ();
+ }
+
+ if ((flags & ORIG_NAME) != 0)
+ {
+ while (true)
+ {
+ int c = eof_read ();
+ if (c == 0)
+ break;
+ }
+ }
+
+ if ((flags & COMMENT) != 0)
+ {
+ while (true)
+ {
+ int c = eof_read ();
+ if (c == 0)
+ break;
+ }
+ }
+
+ if ((flags & HEAD_CRC) != 0)
+ {
+ // FIXME: consider checking CRC of the header.
+ eof_read ();
+ eof_read ();
+ }
+
+ crc = new CRC32 ();
+ }
+
+ public int read (byte[] buf, int off, int len) throws IOException
+ {
+ if (eos)
+ return -1;
+ int r = super.read(buf, off, len);
+ if (r == -1)
+ {
+ eos = true;
+ int header_crc = read4 ();
+ if (crc.getValue() != header_crc)
+ throw new ZipException ("corrupted gzip file");
+ // Read final `ISIZE' field.
+ // FIXME: should we check this length?
+ read4 ();
+ return -1;
+ }
+ crc.update(buf, off, r);
+ return r;
+ }
+
+ private final int read4 () throws IOException
+ {
+ int byte0 = in.read();
+ int byte1 = in.read();
+ int byte2 = in.read();
+ int byte3 = in.read();
+ if (byte3 < 0)
+ throw new ZipException (".zip archive ended prematurely");
+ return ((byte3 & 0xFF) << 24) + ((byte2 & 0xFF) << 16)
+ + ((byte1 & 0xFF) << 8) + (byte0 & 0xFF);
+ }
+
+ // Checksum used by this input stream.
+ protected CRC32 crc;
+
+ // Indicates whether end-of-stream has been reached.
+ protected boolean eos;
+
+ // Some constants from zlib.
+ static final int Z_DEFLATED = 8;
+ static final int HEAD_CRC = 0x02;
+ static final int EXTRA_FIELD = 0x04;
+ static final int ORIG_NAME = 0x08;
+ static final int COMMENT = 0x10;
+ static final int RESERVED = 0xe0;
+}
diff --git a/libjava/java/util/zip/GZIPOutputStream.java b/libjava/java/util/zip/GZIPOutputStream.java
new file mode 100644
index 0000000..1d93fd1
--- /dev/null
+++ b/libjava/java/util/zip/GZIPOutputStream.java
@@ -0,0 +1,88 @@
+// GZIPOutputStream.java - Create a file in gzip format.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util.zip;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class GZIPOutputStream extends DeflaterOutputStream
+{
+ public void close () throws IOException
+ {
+ finish ();
+ out.close ();
+ }
+
+ public void finish () throws IOException
+ {
+ super.finish();
+ put4 ((int) crc.getValue());
+ put4 (def.getTotalIn());
+ }
+
+ public GZIPOutputStream (OutputStream out) throws IOException
+ {
+ this (out, 512);
+ }
+
+ public GZIPOutputStream (OutputStream out, int readsize) throws IOException
+ {
+ super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), readsize);
+
+ put2 (GZIPInputStream.GZIP_MAGIC);
+ out.write (GZIPInputStream.Z_DEFLATED);
+ // No flags for now.
+ out.write (0);
+ // No time either.
+ put2 (0);
+ put2 (0);
+ // No xflags either.
+ out.write (0);
+ // FIXME: unknown OS.
+ out.write (255);
+
+ crc = new CRC32 ();
+ }
+
+ public synchronized void write (byte[] buf, int off, int len)
+ throws IOException
+ {
+ super.write(buf, off, len);
+ crc.update(buf, off, len);
+ }
+
+ private final void put2 (int i) throws IOException
+ {
+ out.write (i);
+ out.write (i >> 8);
+ }
+
+ private final void put4 (int i) throws IOException
+ {
+ out.write (i);
+ out.write (i >> 8);
+ out.write (i >> 16);
+ out.write (i >> 24);
+ }
+
+ // Checksum used by this stream.
+ protected CRC32 crc;
+}
diff --git a/libjava/java/util/zip/Inflater.java b/libjava/java/util/zip/Inflater.java
new file mode 100644
index 0000000..724b5b4
--- /dev/null
+++ b/libjava/java/util/zip/Inflater.java
@@ -0,0 +1,101 @@
+// Inflater.java - Decompress a data stream.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util.zip;
+
+import gnu.gcj.RawData;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+public class Inflater
+{
+ public native void end ();
+
+ protected void finalize ()
+ {
+ end ();
+ }
+
+ public synchronized boolean finished ()
+ {
+ return is_finished;
+ }
+
+ public native int getAdler ();
+ public native int getRemaining ();
+ public native int getTotalIn ();
+ public native int getTotalOut ();
+
+ public int inflate (byte[] buf) throws DataFormatException
+ {
+ return inflate (buf, 0, buf.length);
+ }
+
+ public native int inflate (byte[] buf, int off, int len)
+ throws DataFormatException;
+
+ private native void init (boolean noHeader);
+
+ public Inflater ()
+ {
+ this (false);
+ }
+
+ public Inflater (boolean noHeader)
+ {
+ init (noHeader);
+ }
+
+ public synchronized boolean needsDictionary ()
+ {
+ return dict_needed;
+ }
+
+ public synchronized boolean needsInput ()
+ {
+ return getRemaining () == 0;
+ }
+
+ public native void reset ();
+
+ public void setDictionary (byte[] buf)
+ {
+ setDictionary (buf, 0, buf.length);
+ }
+
+ public native void setDictionary (byte[] buf, int off, int len);
+
+ public void setInput (byte[] buf)
+ {
+ setInput (buf, 0, buf.length);
+ }
+
+ public native void setInput (byte[] buf, int off, int len);
+
+ // The zlib stream.
+ private RawData zstream;
+
+ // True if finished.
+ private boolean is_finished;
+
+ // True if dictionary needed.
+ private boolean dict_needed;
+
+ // Total number of bytes made available at last setInput.
+ private int last_input_count;
+}
diff --git a/libjava/java/util/zip/InflaterInputStream.java b/libjava/java/util/zip/InflaterInputStream.java
index 1b6290a..7ee4455 100644
--- a/libjava/java/util/zip/InflaterInputStream.java
+++ b/libjava/java/util/zip/InflaterInputStream.java
@@ -1,3 +1,5 @@
+// InflaterInputStream.java - Input stream filter for decompressing.
+
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@@ -7,14 +9,94 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
-import java.io.*;
-/** Placefolder - very incomplete. */
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * @author Tom Tromey
+ * @date May 17, 1999
+ */
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
public class InflaterInputStream extends FilterInputStream
{
- public InflaterInputStream(InputStream in)
+ protected void fill () throws IOException
+ {
+ len = in.read(buf, 0, buf.length);
+ if (len != -1)
+ inf.setInput(buf, 0, len);
+ }
+
+ public InflaterInputStream (InputStream in)
+ {
+ this (in, new Inflater (), 512);
+ }
+
+ public InflaterInputStream (InputStream in, Inflater infl)
{
- super(in);
+ this (in, infl, 512);
}
+
+ public InflaterInputStream (InputStream in, Inflater infl, int bufsize)
+ {
+ super (in);
+ this.inf = infl;
+ this.buf = new byte[bufsize];
+ }
+
+ public int read () throws IOException
+ {
+ byte[] buf = new byte[1];
+ int r = read (buf, 0, 1);
+ if (r != -1)
+ r = buf[0] & 0xff;
+ return r;
+ }
+
+ public int read (byte[] buf, int off, int len) throws IOException
+ {
+ if (inf.finished())
+ return -1;
+ if (inf.needsInput())
+ fill ();
+ if (inf.needsDictionary())
+ return -1;
+ return inf.inflate(buf, off, len);
+ }
+
+ public long skip (long n) throws IOException
+ {
+ if (n == 0)
+ return 0;
+
+ int min = (int) Math.min(n, 1024);
+ byte[] buf = new byte[min];
+
+ long s = 0;
+ while (n > 0)
+ {
+ int r = read (buf, 0, min);
+ if (r == -1)
+ break;
+ n -= r;
+ s += r;
+ }
+
+ return s;
+ }
+
+ // Buffer for delivering uncompressed data to inflater.
+ protected byte[] buf;
+
+ // Inflater used to decompress data.
+ protected Inflater inf;
+
+ // Number of read bytes in buf.
+ protected int len;
}
diff --git a/libjava/java/util/zip/ZipEntry.java b/libjava/java/util/zip/ZipEntry.java
index 9eb34ba..7035ab5 100644
--- a/libjava/java/util/zip/ZipEntry.java
+++ b/libjava/java/util/zip/ZipEntry.java
@@ -39,6 +39,10 @@ public class ZipEntry
public ZipEntry (String name)
{
+ if (name == null)
+ throw new NullPointerException ();
+ if (name.length() > 65535)
+ throw new IllegalArgumentException ();
this.name = name;
}
@@ -69,17 +73,45 @@ public class ZipEntry
return false;
}
- public void setComment (String comment) { this.comment = comment; }
+ public void setComment (String comment)
+ {
+ if (comment != null && comment.length() > 65535)
+ throw new IllegalArgumentException ();
+ this.comment = comment;
+ }
- public void setCrc (long crc) { this.crc = crc; }
+ public void setCrc (long crc)
+ {
+ if (crc < 0 || crc > 0xffffffff)
+ throw new IllegalArgumentException ();
+ this.crc = crc;
+ }
- public void setExtra (byte[] extra) { this.extra = extra; }
+ public void setExtra (byte[] extra)
+ {
+ if (extra != null && extra.length > 65535)
+ throw new IllegalArgumentException ();
+ this.extra = extra;
+ }
- public void setMethod(int method) { this.method = method; }
+ public void setMethod (int method)
+ {
+ if (method != DEFLATED && method != STORED)
+ throw new IllegalArgumentException ();
+ this.method = method;
+ }
- public void setSize (long size) { this.size = size; }
+ public void setSize (long size)
+ {
+ if (size < 0 || size > 0xffffffff)
+ throw new IllegalArgumentException ();
+ this.size = size;
+ }
- public void setTime (long time) { this.time = time; }
+ public void setTime (long time)
+ {
+ this.time = time;
+ }
private final static short[] daysToMonthStart = {
//Jan Feb Mar Apr May Jun Jul
diff --git a/libjava/java/util/zip/ZipFile.java b/libjava/java/util/zip/ZipFile.java
index 9085ec9..bfb077d 100644
--- a/libjava/java/util/zip/ZipFile.java
+++ b/libjava/java/util/zip/ZipFile.java
@@ -1,3 +1,5 @@
+// ZipFile.java - Read contents of a ZIP file.
+
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@@ -9,16 +11,13 @@ details. */
package java.util.zip;
import java.io.*;
-/** UNFINISHED, but can read non-comrepssed .zip archives. */
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
public class ZipFile implements ZipConstants
{
-
- ZipEntry entries;
- int numEntries;
- RandomAccessFile file;
- String name;
-
public ZipFile (String fname) throws IOException
{
file = new RandomAccessFile(fname, "r");
@@ -35,7 +34,7 @@ public class ZipFile implements ZipConstants
{
long size = file.length ();
if (size < ZipConstants.END_CENTRAL_DIR_SIZE)
- throw new IOException ("zipfile too short");
+ throw new ZipException ("zipfile too short");
// We do not handle a "zipfile comment", which the appnote says can
// be at the end of a .zip file. We could handle this by seeking
// to the beginning and reading forwards.
@@ -44,7 +43,7 @@ public class ZipFile implements ZipConstants
|| file.read() != 'K'
|| file.read() != '\005'
|| file.read() != '\006')
- throw new IOException("not a valid zipfile");
+ throw new ZipException("not a valid zipfile");
file.skipBytes(6);
numEntries = readu2();
int dir_size = read4 (); // Read "size of the central directory".
@@ -103,7 +102,6 @@ public class ZipFile implements ZipConstants
public void close() throws IOException
{
- // FIXME - check this
file.close();
entries = null;
numEntries = 0;
@@ -121,14 +119,17 @@ public class ZipFile implements ZipConstants
public InputStream getInputStream(ZipEntry ze) throws IOException
{
- // FIXME - does not handle compression!
byte[] buffer = new byte[(int) ze.getSize()];
int data_offset = ZipConstants.LOCAL_FILE_HEADER_SIZE + name.length();
if (ze.extra != null)
data_offset += ze.extra.length;
file.seek(ze.relativeOffset + data_offset);
file.readFully(buffer);
- return new ByteArrayInputStream(buffer);
+
+ InputStream is = new ByteArrayInputStream (buffer);
+ if (ze.getMethod() == ZipEntry.DEFLATED)
+ is = new InflaterInputStream (is);
+ return is;
}
public String getName () { return name; }
@@ -138,7 +139,7 @@ public class ZipFile implements ZipConstants
int byte0 = file.read();
int byte1 = file.read();
if (byte0 < 0 || byte1 < 0)
- throw new EOFException(".zip archive ended prematurely");
+ throw new ZipException (".zip archive ended prematurely");
return ((byte1 & 0xFF) << 8) | (byte0 & 0xFF);
}
@@ -149,10 +150,15 @@ public class ZipFile implements ZipConstants
int byte2 = file.read();
int byte3 = file.read();
if (byte3 < 0)
- throw new EOFException(".zip archive ended prematurely");
+ throw new ZipException (".zip archive ended prematurely");
return ((byte3 & 0xFF) << 24) + ((byte2 & 0xFF) << 16)
+ ((byte1 & 0xFF) << 8) + (byte0 & 0xFF);
}
+
+ ZipEntry entries;
+ int numEntries;
+ RandomAccessFile file;
+ String name;
}
class ZipEnumeration implements java.util.Enumeration
diff --git a/libjava/java/util/zip/ZipInputStream.java b/libjava/java/util/zip/ZipInputStream.java
index 8512896..f2e042b 100644
--- a/libjava/java/util/zip/ZipInputStream.java
+++ b/libjava/java/util/zip/ZipInputStream.java
@@ -168,14 +168,14 @@ public class ZipInputStream extends InflaterInputStream
{
int sig = read4();
if (sig != 0x04034b50)
- throw new IOException("bad/missing magic number at end of .zip entry");
+ throw new ZipException("bad/missing magic number at end of .zip entry");
int crc = read4();
int compressedSize = read4();
int uncompressedSize = read4();
if (current.compressedSize != compressedSize
|| current.size != uncompressedSize
|| current.crc != crc)
- throw new IOException("bad data descriptor at end of .zip entry");
+ throw new ZipException("bad data descriptor at end of .zip entry");
}
current = null;
avail = 0;
diff --git a/libjava/java/util/zip/ZipOutputStream.java b/libjava/java/util/zip/ZipOutputStream.java
index 18f4d38..f4ce7ac 100644
--- a/libjava/java/util/zip/ZipOutputStream.java
+++ b/libjava/java/util/zip/ZipOutputStream.java
@@ -9,65 +9,268 @@ details. */
package java.util.zip;
import java.io.*;
-/** JUST AN INCOMPLETE STUB! */
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
public class ZipOutputStream extends DeflaterOutputStream
implements ZipConstants
{
- ZipEntry current;
- int method = DEFLATED;
- int level = 3; // FIXME - should be DEFAULT_COMPRESSION
- String comment;
-
public static final int STORED = 0;
public static final int DEFLATED = 8;
- public ZipOutputStream (OutputStream out)
+ public void close () throws IOException
{
- super(out);
+ finish ();
+ out.close();
+ }
+
+ public void closeEntry () throws IOException
+ {
+ int uncompressed_size = def.getTotalIn();
+ int compressed_size = def.getTotalOut();
+ int crc = (int) (filter.getChecksum().getValue());
+
+ bytes_written += compressed_size;
+
+ bytes_written += put4 (0x08074b50);
+ if (current.getCrc() == -1 || current.getCompressedSize() == -1
+ || current.getSize() == -1)
+ {
+ current.setCrc(crc);
+ current.compressedSize = compressed_size;
+ current.setSize(uncompressed_size);
+ }
+ else
+ {
+ if (current.getCrc() != crc
+ || current.getCompressedSize() != compressed_size
+ || current.getSize() != uncompressed_size)
+ throw new ZipException ("zip entry field incorrect");
+ }
+ bytes_written += put4 ((int) (current.getCrc()));
+ bytes_written += put4 ((int) (current.getCompressedSize()));
+ bytes_written += put4 ((int) (current.getSize()));
+
+ current.next = chain;
+ chain = current;
+ current = null;
+ filter = null;
+ }
+
+ public void finish () throws IOException
+ {
+ if (current != null)
+ closeEntry ();
+
+ // Write the central directory.
+ long offset = bytes_written;
+ int count = 0;
+ int bytes = 0;
+ while (chain != null)
+ {
+ bytes += write_entry (chain, false);
+ ++count;
+ chain = chain.next;
+ }
+
+ // Write the end of the central directory record.
+ put4 (0x06054b50);
+ // Disk number.
+ put2 (0);
+ // Another disk number.
+ put2 (0);
+ put2 (count);
+ put4 (bytes);
+ put4 ((int) offset);
+
+ byte[] c = comment.getBytes("8859_1");
+ put2 (c.length);
+ out.write(c);
+ out.write((byte) 0);
}
- public void setLevel (int level) { this.level = level; }
- public void setMethod (int method) { this.method = method; }
- public void setComment(String comment) { this.comment = comment; }
+ // Helper for finish and putNextEntry.
+ private int write_entry (ZipEntry entry, boolean is_local)
+ throws IOException
+ {
+ long offset = bytes_written;
+
+ int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50);
+ if (! is_local)
+ bytes += put_version ();
+ bytes += put_version ();
+
+ boolean crc_after = false;
+ if (is_local
+ && (current.getCrc() == -1 || current.getCompressedSize() == -1
+ || current.getSize() == -1))
+ crc_after = true;
+ // For the bits field we always indicate `normal' compression,
+ // even if that isn't true.
+ bytes += put2 (crc_after ? (1 << 3) : 0);
+ bytes += put2 (entry.method);
+
+ bytes += put2(0); // time - FIXME
+ bytes += put2(0); // date - FIXME
+
+ if (crc_after)
+ {
+ // CRC, compressedSize, and Size are always 0 in this header.
+ // The actual values are given after the entry.
+ bytes += put4 (0);
+ bytes += put4 (0);
+ bytes += put4 (0);
+ }
+ else
+ {
+ bytes += put4 ((int) (entry.getCrc()));
+ bytes += put4 ((int) (entry.getCompressedSize()));
+ bytes += put4 ((int) (entry.getSize()));
+ }
+
+ byte[] name = entry.name.getBytes("8859_1");
+ bytes += put2 (name.length);
+ bytes += put2 (entry.extra == null ? 0 : entry.extra.length);
+
+ byte[] comment = null;
+ if (! is_local)
+ {
+ if (entry.getComment() == null)
+ bytes += put2 (0);
+ else
+ {
+ comment = entry.getComment().getBytes("8859_1");
+ bytes += put2 (comment.length);
+ }
+
+ // Disk number start.
+ bytes += put2 (0);
+ // Internal file attributes.
+ bytes += put2 (0);
+ // External file attributes.
+ bytes += put2 (0);
+ // Relative offset of local header.
+ bytes += put2 ((int) offset);
+ }
+
+ out.write (name);
+ out.write ((byte) 0);
+ bytes += name.length + 1;
+ if (entry.extra != null)
+ {
+ out.write(entry.extra);
+ out.write((byte) 0);
+ bytes += entry.extra.length + 1;
+ }
+ if (comment != null)
+ {
+ out.write(comment);
+ out.write((byte) 0);
+ bytes += comment.length + 1;
+ }
+
+ bytes_written += bytes;
+ return bytes;
+ }
public void putNextEntry (ZipEntry entry) throws IOException
{
- put4(0x04034b50);
- put2(0); // version - FIXME
- put2(0); // bits - FIXME
+ if (current != null)
+ closeEntry ();
+
if (entry.method < 0 )
entry.method = method;
- put2(entry.method);
- put2(0); // time - FIXME
- put2(0); // date - FIXME
- put4((int) entry.crc);
- put4((int) entry.compressedSize); // FIXME
- put4((int) entry.size); // FIXME
- put2(entry.name.length());
- put2(entry.extra == null ? 0 : entry.extra.length);
- byte[] name = entry.name.getBytes("8859_1");
- out.write(name);
- if (entry.extra != null)
- out.write(entry.extra);
- throw new Error ("java.util.zip.ZipOutputStream.putNextEntry: not implemented");
+ if (entry.method == STORED)
+ {
+ if (entry.getSize() == -1 || entry.getCrc() == -1)
+ throw new ZipException ("required entry not set");
+ // Just in case.
+ entry.compressedSize = entry.getSize();
+ }
+ write_entry (entry, true);
+ current = entry;
+ int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level;
+ def.reset();
+ def.setLevel(compr);
+ filter = new CheckedOutputStream (new DeflaterOutputStream (out, def),
+ new CRC32 ());
}
- public void closeEntry () throws IOException
+ public void setLevel (int level)
{
+ if (level != Deflater.DEFAULT_COMPRESSION
+ && (level < Deflater.NO_COMPRESSION
+ || level > Deflater.BEST_COMPRESSION))
+ throw new IllegalArgumentException ();
+ this.level = level;
}
- private void put2 (int i) throws IOException
+ public void setMethod (int method)
+ {
+ if (method != DEFLATED && method != STORED)
+ throw new IllegalArgumentException ();
+ this.method = method;
+ }
+
+ public void setComment (String comment)
+ {
+ if (comment.length() > 65535)
+ throw new IllegalArgumentException ();
+ this.comment = comment;
+ }
+
+ public synchronized void write (byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (filter == null)
+ throw new ZipException ("no open zip entry");
+ filter.write(buf, off, len);
+ }
+
+ public ZipOutputStream (OutputStream out)
+ {
+ super (out);
+ def = new Deflater (level, true);
+ }
+
+ private int put2 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
+ return 2;
}
- private void put4 (int i) throws IOException
+ private int put4 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
out.write (i >> 16);
out.write (i >> 24);
+ return 4;
}
+
+ private int put_version () throws IOException
+ {
+ // FIXME: for now we assume Unix, and we ignore the version
+ // number.
+ return put2 (3 << 8);
+ }
+
+ // The entry we are currently writing, or null if we've called
+ // closeEntry.
+ private ZipEntry current;
+ // The chain of entries which have been written to this file.
+ private ZipEntry chain;
+ // The output stream to which data should be sent.
+ private CheckedOutputStream filter;
+
+ private int method = DEFLATED;
+ private int level = Deflater.DEFAULT_COMPRESSION;
+ private String comment = "";
+ private long bytes_written;
+
+ // The Deflater we use.
+ private Deflater def;
}
diff --git a/libjava/java/util/zip/natDeflater.cc b/libjava/java/util/zip/natDeflater.cc
new file mode 100644
index 0000000..07cf009
--- /dev/null
+++ b/libjava/java/util/zip/natDeflater.cc
@@ -0,0 +1,209 @@
+// natDeflater.cc - Implementation of Deflater native methods.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// Written by Tom Tromey <tromey@cygnus.com>
+
+#include <config.h>
+
+#include <zlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+
+#include <java/util/zip/Deflater.h>
+#include <java/util/zip/DataFormatException.h>
+
+#include <java/lang/InternalError.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+
+extern void *_Jv_ZMalloc (void *, uInt nitems, uInt size);
+extern void _Jv_ZFree (void *, void *addr);
+
+
+
+jint
+java::util::zip::Deflater::deflate (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ s->next_out = (Bytef *) (elements (buf) + off);
+ s->avail_out = len;
+
+ switch (::deflate (s, flush_flag))
+ {
+ case Z_STREAM_END:
+ is_finished = true;
+ if (s->avail_out == len)
+ return -1;
+ break;
+
+ case Z_STREAM_ERROR:
+ case Z_BUF_ERROR:
+ // FIXME?
+ _Jv_Throw (new java::lang::InternalError);
+ break;
+
+ case Z_OK:
+ break;
+ }
+
+ return len - s->avail_out;
+}
+
+void
+java::util::zip::Deflater::end ()
+{
+ JvSynchronize sync (this);
+ // Just ignore errors.
+ deflateEnd ((z_streamp) zstream);
+ _Jv_Free (zstream);
+ zstream = NULL;
+}
+
+void
+java::util::zip::Deflater::finish ()
+{
+ JvSynchronize sync (this);
+ flush_flag = Z_FINISH;
+}
+
+jint
+java::util::zip::Deflater::getAdler ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->adler;
+}
+
+jint
+java::util::zip::Deflater::getTotalIn ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_in;
+}
+
+jint
+java::util::zip::Deflater::getTotalOut ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_out;
+}
+
+jboolean
+java::util::zip::Deflater::needsInput ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->avail_in - last_input_count == 0;
+}
+
+void
+java::util::zip::Deflater::reset ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ // Just ignore errors.
+ deflateReset (s);
+ flush_flag = 0;
+}
+
+void
+java::util::zip::Deflater::setDictionary (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ // Ignore errors.
+ deflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
+}
+
+void
+java::util::zip::Deflater::setInput (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ last_input_count = len;
+ s->next_in = (Bytef *) (elements (buf) + off);
+ s->avail_in = len;
+}
+
+void
+java::util::zip::Deflater::update ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ int strat;
+ switch (strategy)
+ {
+ case DEFAULT_STRATEGY:
+ strat = Z_DEFAULT_STRATEGY;
+ break;
+ case FILTERED:
+ strat = Z_FILTERED;
+ break;
+ case HUFFMAN_ONLY:
+ strat = Z_HUFFMAN_ONLY;
+ break;
+ }
+
+ // Ignore errors.
+ deflateParams (s, level, strat);
+}
+
+void
+java::util::zip::Deflater::init (jint level, jboolean no_header)
+{
+ z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
+ stream->next_in = Z_NULL;
+ stream->avail_in = 0;
+ stream->zalloc = _Jv_ZMalloc;
+ stream->zfree = _Jv_ZFree;
+ stream->opaque = NULL;
+
+ // Handle NO_HEADER using undocumented zlib feature.
+ int wbits = MAX_WBITS;
+ if (no_header)
+ wbits = - wbits;
+
+#define DEFAULT_MEM_LEVEL 8
+ if (deflateInit2 (stream, level, Z_DEFLATED, wbits,
+ DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
+ {
+ jstring msg = NULL;
+ if (stream->msg != NULL)
+ msg = JvNewStringLatin1 (stream->msg);
+ _Jv_Throw (new java::lang::InternalError (msg));
+ }
+
+ zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
+ is_finished = false;
+ flush_flag = 0;
+}
diff --git a/libjava/java/util/zip/natInflater.cc b/libjava/java/util/zip/natInflater.cc
new file mode 100644
index 0000000..b33ab50
--- /dev/null
+++ b/libjava/java/util/zip/natInflater.cc
@@ -0,0 +1,202 @@
+// natInflater.cc - Implementation of Inflater native methods.
+
+/* Copyright (C) 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// Written by Tom Tromey <tromey@cygnus.com>
+
+#include <config.h>
+
+#include <zlib.h>
+
+#include <cni.h>
+#include <jvm.h>
+
+#include <java/util/zip/Inflater.h>
+#include <java/util/zip/DataFormatException.h>
+
+#include <java/lang/InternalError.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/OutOfMemoryError.h>
+
+
+
+// A couple of helper functions used to interface with zlib's
+// allocation.
+
+void *
+_Jv_ZMalloc (void *, uInt nitems, uInt size)
+{
+ return _Jv_Malloc (nitems * size);
+}
+
+void
+_Jv_ZFree (void *, void *addr)
+{
+ _Jv_Free (addr);
+}
+
+
+
+void
+java::util::zip::Inflater::end ()
+{
+ JvSynchronize sync (this);
+ // Just ignore errors.
+ inflateEnd ((z_streamp) zstream);
+ _Jv_Free (zstream);
+ zstream = NULL;
+}
+
+jint
+java::util::zip::Inflater::getAdler ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->adler;
+}
+
+jint
+java::util::zip::Inflater::getRemaining ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->avail_in - last_input_count;
+}
+
+jint
+java::util::zip::Inflater::getTotalIn ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_in;
+}
+
+jint
+java::util::zip::Inflater::getTotalOut ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_out;
+}
+
+jint
+java::util::zip::Inflater::inflate (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ s->next_out = (Bytef *) (elements (buf) + off);
+ s->avail_out = len;
+
+ switch (::inflate (s, Z_SYNC_FLUSH))
+ {
+ case Z_STREAM_END:
+ is_finished = true;
+ if (s->avail_out == len)
+ return -1;
+ break;
+
+ case Z_NEED_DICT:
+ dict_needed = true;
+ break;
+
+ case Z_DATA_ERROR:
+ _Jv_Throw (new java::util::zip::DataFormatException);
+ break;
+
+ case Z_MEM_ERROR:
+ _Jv_Throw (new java::lang::OutOfMemoryError);
+ break;
+
+ case Z_BUF_ERROR:
+ // FIXME?
+ _Jv_Throw (new java::lang::InternalError);
+ break;
+
+ case Z_OK:
+ break;
+ }
+
+ return len - s->avail_out;
+}
+
+void
+java::util::zip::Inflater::reset ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ // Just ignore errors.
+ inflateReset (s);
+}
+
+void
+java::util::zip::Inflater::setDictionary (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ // Ignore errors.
+ inflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
+ dict_needed = false;
+}
+
+void
+java::util::zip::Inflater::setInput (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ _Jv_Throw (new java::lang::NullPointerException);
+ if (off < 0 || len < 0 || off + len > buf->length)
+ _Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
+
+ last_input_count = len;
+ s->next_in = (Bytef *) (elements (buf) + off);
+ s->avail_in = len;
+}
+
+void
+java::util::zip::Inflater::init (jboolean no_header)
+{
+ z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
+ stream->next_in = Z_NULL;
+ stream->avail_in = 0;
+ stream->zalloc = _Jv_ZMalloc;
+ stream->zfree = _Jv_ZFree;
+ stream->opaque = NULL;
+
+ // Handle NO_HEADER using undocumented zlib feature.
+ int wbits = MAX_WBITS;
+ if (no_header)
+ wbits = - wbits;
+
+ if (inflateInit2 (stream, wbits) != Z_OK)
+ {
+ jstring msg = NULL;
+ if (stream->msg != NULL)
+ msg = JvNewStringLatin1 (stream->msg);
+ _Jv_Throw (new java::lang::InternalError (msg));
+ }
+
+ zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
+ is_finished = false;
+ dict_needed = false;
+}