Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@gnome.org>2004-10-02 22:48:07 +0400
committerMiguel de Icaza <miguel@gnome.org>2004-10-02 22:48:07 +0400
commitff0d74eeb5a9fb33d0a7e26de714b0d7494d2aaa (patch)
tree18dd8ef86f97f5a1fcd01b4181513600cb1dff26 /mcs/class/System/System.IO.Compression/DeflateStream.cs
parent5a3fd5b35d482a650036ba311aa90359c3dc43fb (diff)
Add System.IO.Compression from Chris Lahey (clahey@ximian.com)
svn path=/trunk/mcs/; revision=34610
Diffstat (limited to 'mcs/class/System/System.IO.Compression/DeflateStream.cs')
-rw-r--r--mcs/class/System/System.IO.Compression/DeflateStream.cs403
1 files changed, 403 insertions, 0 deletions
diff --git a/mcs/class/System/System.IO.Compression/DeflateStream.cs b/mcs/class/System/System.IO.Compression/DeflateStream.cs
new file mode 100644
index 00000000000..c0ba974f7b1
--- /dev/null
+++ b/mcs/class/System/System.IO.Compression/DeflateStream.cs
@@ -0,0 +1,403 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+//
+// DeflateStream.cs
+//
+// Authors:
+// Christopher James Lahey <clahey@ximian.com>
+//
+// (c) 2004 Novell, Inc. <http://www.novell.com>
+//
+
+#if NET_2_0
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Messaging;
+
+namespace System.IO.Compression {
+ class DeflateStream : Stream
+ {
+ private Stream compressedStream;
+ private CompressionMode mode;
+ private bool leaveOpen;
+ private bool open;
+ private IntPtr z_stream;
+
+ private const int BUFFER_SIZE = 4096;
+ private IntPtr sized_buffer;
+ static int bytes_read = 0;
+ private bool finished = false;
+ private enum ZReturnConsts {
+ Z_OK = 0,
+ Z_STREAM_END = 1,
+ Z_NEED_DICT = 2,
+ Z_STREAM_ERROR = -2,
+ Z_DATA_ERROR = -3,
+ Z_MEM_ERROR = -4,
+ Z_BUF_ERROR = -5,
+ }
+ private enum ZFlushConsts {
+ Z_NO_FLUSH = 0,
+ Z_PARTIAL_FLUSH = 1, /* will be removed, use Z_SYNC_FLUSH instead */
+ Z_SYNC_FLUSH = 2,
+ Z_FULL_FLUSH = 3,
+ Z_FINISH = 4,
+ Z_BLOCK = 5,
+ };
+
+
+ [DllImport("MonoPosixHelper")]
+ static extern IntPtr create_z_stream(CompressionMode compress, bool gzip);
+ [DllImport("MonoPosixHelper")]
+ static extern void free_z_stream(IntPtr z_stream);
+ [DllImport("MonoPosixHelper")]
+ static extern void z_stream_set_next_in(IntPtr z_stream, IntPtr next_in);
+ [DllImport("MonoPosixHelper")]
+ static extern void z_stream_set_avail_in(IntPtr z_stream, int avail_in);
+ [DllImport("MonoPosixHelper")]
+ static extern int z_stream_get_avail_in(IntPtr z_stream);
+ [DllImport("MonoPosixHelper")]
+ static extern void z_stream_set_next_out(IntPtr z_stream, IntPtr next_out);
+ [DllImport("MonoPosixHelper")]
+ static extern void z_stream_set_avail_out(IntPtr z_stream, int avail_out);
+ [DllImport("MonoPosixHelper")]
+ static extern ZReturnConsts z_stream_inflate(IntPtr z_stream, ref int avail_out);
+ [DllImport("MonoPosixHelper")]
+ static extern ZReturnConsts z_stream_deflate(IntPtr z_stream, ZFlushConsts flush, IntPtr next_out, ref int avail_out);
+
+ delegate int ReadMethod (byte[] array, int offset, int count);
+ delegate void WriteMethod(byte[] array, int offset, int count);
+
+ internal DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen, bool gzip) {
+ this.compressedStream = compressedStream;
+ this.mode = mode;
+ this.leaveOpen = leaveOpen;
+ this.sized_buffer = Marshal.AllocHGlobal (BUFFER_SIZE);
+ this.z_stream = create_z_stream (mode, gzip);
+ if (z_stream == IntPtr.Zero) {
+ throw new OutOfMemoryException ();
+ }
+ this.open = true;
+ if (mode == CompressionMode.Compress) {
+ Flush();
+ }
+ }
+
+ public DeflateStream (Stream compressedStream, CompressionMode mode) :
+ this (compressedStream, mode, false, false) { }
+
+ public DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen) :
+ this (compressedStream, mode, leaveOpen, false) { }
+
+ ~DeflateStream () {
+ Marshal.FreeHGlobal (sized_buffer);
+ }
+
+ public override void Close () {
+ FlushInternal (true);
+
+ if (mode == CompressionMode.Decompress && compressedStream.CanSeek) {
+ int avail_in = z_stream_get_avail_in (z_stream);
+ if (avail_in != 0) {
+ compressedStream.Seek (- avail_in, SeekOrigin.Current);
+ z_stream_set_avail_in (z_stream, 0);
+ }
+ }
+
+ free_z_stream (z_stream);
+ z_stream = IntPtr.Zero;
+
+ if (!leaveOpen) {
+ compressedStream.Close();
+ }
+
+ open = false;
+ }
+
+ private int ReadInternal(byte[] array, int offset, int count) {
+
+ int buffer_size;
+ if (finished)
+ return 0;
+
+ if (compressedStream.CanSeek)
+ buffer_size = BUFFER_SIZE;
+ else
+ buffer_size = 1;
+
+ IntPtr buffer = Marshal.AllocHGlobal(count);
+ try {
+ int avail_out;
+
+ avail_out = count;
+ z_stream_set_next_out (z_stream, buffer);
+
+ while (avail_out != 0 && !finished) {
+ if (z_stream_get_avail_in (z_stream) == 0) {
+ byte[] read_buf = new byte[buffer_size];
+ int length_read = compressedStream.Read (read_buf, 0, buffer_size);
+ bytes_read += length_read;
+ if (length_read == 0) {
+ break;
+ }
+ Marshal.Copy (read_buf, 0, sized_buffer, length_read);
+ z_stream_set_next_in (z_stream, sized_buffer);
+ z_stream_set_avail_in (z_stream, length_read);
+ }
+ ZReturnConsts ret_val = z_stream_inflate(z_stream, ref avail_out);
+ switch (ret_val) {
+ case ZReturnConsts.Z_OK:
+ break;
+ case ZReturnConsts.Z_STREAM_END:
+ finished = true;
+ break;
+ case ZReturnConsts.Z_NEED_DICT:
+ throw new InvalidDataException ("ZLib stream requires a dictionary.");
+ case ZReturnConsts.Z_DATA_ERROR:
+ throw new InvalidDataException ("Invalid ZLib data.");
+ case ZReturnConsts.Z_STREAM_ERROR:
+ throw new InvalidOperationException ("Internal DeflateStream error.");
+ case ZReturnConsts.Z_MEM_ERROR:
+ throw new OutOfMemoryException ();
+ case ZReturnConsts.Z_BUF_ERROR:
+ throw new InvalidOperationException ("Internal DeflateStream error: Buf error.");
+ }
+ }
+ if (count != avail_out)
+ Marshal.Copy (buffer, array, offset, count - avail_out);
+ return count - avail_out;
+ } finally {
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public override int Read (byte[] dest, int dest_offset, int count)
+ {
+ if (dest == null)
+ throw new ArgumentNullException ("Destination array is null.");
+ if (!CanRead)
+ throw new NotSupportedException ("Stream does not support reading.");
+ int len = dest.Length;
+ if (dest_offset < 0 || count < 0)
+ throw new ArgumentException ("Dest or count is negative.");
+ if (dest_offset > len)
+ throw new ArgumentException ("destination offset is beyond array size");
+ if ((dest_offset + count) > len)
+ throw new ArgumentException ("Reading would overrun buffer");
+
+ return ReadInternal (dest, dest_offset, count);
+ }
+
+
+ private ZReturnConsts do_deflate (ZFlushConsts flush, out int avail_out) {
+ avail_out = BUFFER_SIZE;
+ ZReturnConsts ret_val = z_stream_deflate (z_stream, flush, sized_buffer, ref avail_out);
+ switch (ret_val) {
+ case ZReturnConsts.Z_STREAM_ERROR:
+ throw new InvalidOperationException ("Internal error.");
+ case ZReturnConsts.Z_MEM_ERROR:
+ throw new InvalidOperationException ("Memory error.");
+ }
+ return ret_val;
+ }
+
+ private void WriteInternal(byte[] array, int offset, int count) {
+ IntPtr buffer = Marshal.AllocHGlobal(count);
+ try {
+ int avail_in;
+
+ avail_in = count;
+
+ Marshal.Copy (array, offset, buffer, count);
+ z_stream_set_next_in (z_stream, buffer);
+ z_stream_set_avail_in (z_stream, avail_in);
+ while (avail_in != 0) {
+ int avail_out;
+
+ do_deflate (ZFlushConsts.Z_NO_FLUSH, out avail_out);
+
+ if (avail_out != BUFFER_SIZE) {
+ byte[] output = new byte[BUFFER_SIZE - avail_out];
+ Marshal.Copy (sized_buffer, output, 0, BUFFER_SIZE - avail_out);
+ compressedStream.Write(output, 0, BUFFER_SIZE - avail_out);
+ }
+
+ avail_in = z_stream_get_avail_in (z_stream);
+ }
+ } finally {
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public override void Write (byte[] src, int src_offset, int count)
+ {
+ if (src == null)
+ throw new ArgumentNullException ("src");
+
+ if (src_offset < 0)
+ throw new ArgumentOutOfRangeException ("src_offset");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count");
+
+ if (!CanWrite)
+ throw new NotSupportedException ("Stream does not support writing");
+
+ WriteInternal (src, src_offset, count);
+ }
+
+ private void FlushInternal (bool finish) {
+ int avail_out;
+ ZReturnConsts ret_val;
+
+ if (!(open && mode == CompressionMode.Compress && compressedStream.CanWrite))
+ return;
+
+ z_stream_set_next_in (z_stream, IntPtr.Zero);
+ z_stream_set_avail_in (z_stream, 0);
+
+ while (true) {
+ ret_val = do_deflate (finish ? ZFlushConsts.Z_FINISH : ZFlushConsts.Z_SYNC_FLUSH, out avail_out);
+
+ if (BUFFER_SIZE != avail_out) {
+ byte[] output = new byte[BUFFER_SIZE - avail_out];
+ Marshal.Copy (sized_buffer, output, 0, BUFFER_SIZE - avail_out);
+ compressedStream.Write(output, 0, BUFFER_SIZE - avail_out);
+ } else {
+ if (!finish)
+ break;
+ }
+ if (ret_val == ZReturnConsts.Z_STREAM_END)
+ break;
+ }
+
+ compressedStream.Flush();
+ }
+
+ public override void Flush () {
+ FlushInternal (false);
+ }
+
+ public override long Seek (long offset, SeekOrigin origin) {
+ throw new System.NotSupportedException();
+ }
+
+ public override void SetLength (long value) {
+ throw new System.NotSupportedException();
+ }
+
+ public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ if (!CanRead)
+ throw new NotSupportedException ("This stream does not support reading");
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+ if (count + offset > buffer.Length)
+ throw new ArgumentException ("Buffer too small. count/offset wrong.");
+
+ ReadMethod r = new ReadMethod (ReadInternal);
+ return r.BeginInvoke (buffer, offset, count, cback, state);
+ }
+
+ public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
+ AsyncCallback cback, object state)
+ {
+ if (!CanWrite)
+ throw new NotSupportedException ("This stream does not support writing");
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+ if (count + offset > buffer.Length)
+ throw new ArgumentException ("Buffer too small. count/offset wrong.");
+
+ WriteMethod w = new WriteMethod (WriteInternal);
+ return w.BeginInvoke (buffer, offset, count, cback, state);
+ }
+
+ public override int EndRead(IAsyncResult async_result) {
+ if (async_result == null)
+ throw new ArgumentNullException ("async_result");
+
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+ ReadMethod r = ares.AsyncDelegate as ReadMethod;
+ if (r == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+ return r.EndInvoke (async_result);
+ }
+
+ public override void EndWrite (IAsyncResult async_result)
+ {
+ if (async_result == null)
+ throw new ArgumentNullException ("async_result");
+
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+ WriteMethod w = ares.AsyncDelegate as WriteMethod;
+ if (w == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+ w.EndInvoke (async_result);
+ return;
+ }
+
+ public Stream BaseStream {
+ get {
+ return compressedStream;
+ }
+ }
+ public override bool CanRead {
+ get {
+ return open && mode == CompressionMode.Decompress && compressedStream.CanRead;
+ }
+ }
+ public override bool CanSeek {
+ get {
+ return false;
+ }
+ }
+ public override bool CanWrite {
+ get {
+ return open && mode == CompressionMode.Compress && compressedStream.CanWrite;
+ }
+ }
+ public override long Length {
+ get {
+ throw new System.NotSupportedException();
+ }
+ set {
+ throw new System.NotSupportedException();
+ }
+ }
+ public override long Position {
+ get {
+ throw new System.NotSupportedException();
+ }
+ set {
+ throw new System.NotSupportedException();
+ }
+ }
+ }
+}
+#endif