Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System / System.IO.Compression / DefalteStream.jvm.cs
1 // 
2 // DeflateStream.cs
3 //
4 // Authors:
5 //      Konstantin Triger <kostat@mainsoft.com>
6 //
7 // (c) 2008 Mainsoft corp. <http://www.mainsoft.com>
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.IO;
31 using System.Runtime.InteropServices;
32 using System.Runtime.Remoting.Messaging;
33 using java.io;
34 using java.util.zip;
35 using vmw.common;
36
37 namespace System.IO.Compression
38 {
39         public class DeflateStream : Stream
40         {
41                 readonly Stream _baseStream;
42                 readonly InflaterInputStream _reader;
43                 readonly DeflaterOutputStream _writer;
44
45                 readonly bool _leaveOpen;
46                 bool _open;
47
48                 delegate int ReadMethod (byte [] array, int offset, int count);
49                 delegate void WriteMethod (byte [] array, int offset, int count);
50
51                 internal DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen, bool gzip) {
52                         if (compressedStream == null)
53                                 throw new ArgumentNullException ("compressedStream");
54
55                         switch (mode) {
56                         case CompressionMode.Compress:
57                                 if (!compressedStream.CanWrite)
58                                         throw new ArgumentException ("The base stream is not writeable.");
59                                 OutputStream outStream = new OutputStreamImpl(compressedStream);
60                                 _writer = gzip ? new GZIPOutputStream (outStream) : new DeflaterOutputStream (outStream, new Deflater (Deflater.DEFAULT_COMPRESSION, true));
61                                 break;
62                         case CompressionMode.Decompress:
63                                 if (!compressedStream.CanRead)
64                                         throw new ArgumentException ("The base stream is not readable.");
65                                 InputStream inStream = new InputStreamImpl (compressedStream);
66                                 _reader = gzip ? new GZIPInputStream (inStream) : new InflaterInputStream (inStream, new Inflater (true));
67                                 break;
68                         default:
69                                 throw new ArgumentException ("mode");
70                         }
71
72                         _baseStream = compressedStream;
73                         _leaveOpen = leaveOpen;
74                         _open = true;
75                 }
76
77                 public DeflateStream (Stream compressedStream, CompressionMode mode)
78                         :
79                         this (compressedStream, mode, false, false) { }
80
81                 public DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen)
82                         :
83                         this (compressedStream, mode, leaveOpen, false) { }
84
85                 protected override void Dispose (bool disposing) {
86                         if (!_open) {
87                                 base.Dispose (disposing);
88                                 return;
89                         }
90
91                         try {
92                                 FlushInternal (true);
93                                 base.Dispose (disposing);
94                         }
95                         finally {
96                                 _open = false;
97                                 if (!_leaveOpen)
98                                         _baseStream.Close ();
99                         }
100                 }
101
102                 private int ReadInternal (byte [] array, int offset, int count) {
103                         int r = _reader.read (TypeUtils.ToSByteArray (array), offset, count);
104                         return r < 0 ? 0 : r;
105                 }
106
107                 public override int Read (byte [] dest, int dest_offset, int count) {
108                         if (!_open)
109                                 throw new ObjectDisposedException ("DeflateStream");
110                         if (dest == null)
111                                 throw new ArgumentNullException ("Destination array is null.");
112                         if (!CanRead)
113                                 throw new InvalidOperationException ("Stream does not support reading.");
114                         int len = dest.Length;
115                         if (dest_offset < 0 || count < 0)
116                                 throw new ArgumentException ("Dest or count is negative.");
117                         if (dest_offset > len)
118                                 throw new ArgumentException ("destination offset is beyond array size");
119                         if ((dest_offset + count) > len)
120                                 throw new ArgumentException ("Reading would overrun buffer");
121
122                         return ReadInternal (dest, dest_offset, count);
123                 }
124
125                 private void WriteInternal (byte [] array, int offset, int count) {
126                         _writer.write (TypeUtils.ToSByteArray (array), offset, count);
127                 }
128
129                 public override void Write (byte [] src, int src_offset, int count) {
130                         if (!_open)
131                                 throw new ObjectDisposedException ("DeflateStream");
132
133                         if (src == null)
134                                 throw new ArgumentNullException ("src");
135
136                         if (src_offset < 0)
137                                 throw new ArgumentOutOfRangeException ("src_offset");
138
139                         if (count < 0)
140                                 throw new ArgumentOutOfRangeException ("count");
141
142                         if (!CanWrite)
143                                 throw new NotSupportedException ("Stream does not support writing");
144
145                         WriteInternal (src, src_offset, count);
146                 }
147
148                 private void FlushInternal (bool finish) {
149                         if (!_open)
150                                 throw new ObjectDisposedException ("DeflateStream");
151
152                         if (_writer != null) {
153                                 _writer.flush ();
154
155                                 if (finish)
156                                         _writer.finish ();
157                         }
158                 }
159
160                 public override void Flush () {
161                         FlushInternal (false);
162                 }
163
164                 public override long Seek (long offset, SeekOrigin origin) {
165                         throw new System.NotSupportedException ();
166                 }
167
168                 public override void SetLength (long value) {
169                         throw new System.NotSupportedException ();
170                 }
171
172                 public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
173                                                         AsyncCallback cback, object state) {
174                         if (!_open)
175                                 throw new ObjectDisposedException ("DeflateStream");
176
177                         if (!CanRead)
178                                 throw new NotSupportedException ("This stream does not support reading");
179
180                         if (buffer == null)
181                                 throw new ArgumentNullException ("buffer");
182
183                         if (count < 0)
184                                 throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
185
186                         if (offset < 0)
187                                 throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
188
189                         if (count + offset > buffer.Length)
190                                 throw new ArgumentException ("Buffer too small. count/offset wrong.");
191
192                         ReadMethod r = new ReadMethod (ReadInternal);
193                         return r.BeginInvoke (buffer, offset, count, cback, state);
194                 }
195
196                 public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
197                                                         AsyncCallback cback, object state) {
198                         if (!_open)
199                                 throw new ObjectDisposedException ("DeflateStream");
200
201                         if (!CanWrite)
202                                 throw new InvalidOperationException ("This stream does not support writing");
203
204                         if (buffer == null)
205                                 throw new ArgumentNullException ("buffer");
206
207                         if (count < 0)
208                                 throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
209
210                         if (offset < 0)
211                                 throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
212
213                         if (count + offset > buffer.Length)
214                                 throw new ArgumentException ("Buffer too small. count/offset wrong.");
215
216                         WriteMethod w = new WriteMethod (WriteInternal);
217                         return w.BeginInvoke (buffer, offset, count, cback, state);
218                 }
219
220                 public override int EndRead (IAsyncResult async_result) {
221                         if (async_result == null)
222                                 throw new ArgumentNullException ("async_result");
223
224                         AsyncResult ares = async_result as AsyncResult;
225                         if (ares == null)
226                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
227
228                         ReadMethod r = ares.AsyncDelegate as ReadMethod;
229                         if (r == null)
230                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
231
232                         return r.EndInvoke (async_result);
233                 }
234
235                 public override void EndWrite (IAsyncResult async_result) {
236                         if (async_result == null)
237                                 throw new ArgumentNullException ("async_result");
238
239                         AsyncResult ares = async_result as AsyncResult;
240                         if (ares == null)
241                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
242
243                         WriteMethod w = ares.AsyncDelegate as WriteMethod;
244                         if (w == null)
245                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
246
247                         w.EndInvoke (async_result);
248                 }
249
250                 public Stream BaseStream {
251                         get {
252                                 return _baseStream;
253                         }
254                 }
255                 public override bool CanRead {
256                         get {
257                                 return _open && _reader != null;
258                         }
259                 }
260                 public override bool CanSeek {
261                         get {
262                                 return false;
263                         }
264                 }
265                 public override bool CanWrite {
266                         get {
267                                 return _open && _writer != null;
268                         }
269                 }
270                 public override long Length {
271                         get {
272                                 throw new NotSupportedException ();
273                         }
274                 }
275                 public override long Position {
276                         get {
277                                 throw new NotSupportedException ();
278                         }
279                         set {
280                                 throw new NotSupportedException ();
281                         }
282                 }
283
284                 #region InputStreamImpl
285
286                 sealed class InputStreamImpl : InputStream
287                 {
288                         readonly Stream _stream;
289
290                         public InputStreamImpl (Stream stream) {
291                                 _stream = stream;
292                         }
293
294                         public override void close () {
295                                 BaseStream.Close ();
296                         }
297
298                         public override int read () {
299                                 return BaseStream.ReadByte ();
300                         }
301
302                         public override int read (sbyte [] b, int off, int len) {
303                                 int r = BaseStream.Read ((byte []) TypeUtils.ToByteArray (b), off, len);
304                                 return r == 0 ? -1 : r;
305                         }
306
307                         public override long skip (long n) {
308                                 return BaseStream.Seek (n, SeekOrigin.Current);
309                         }
310
311                         public override bool Equals (object obj) {
312                                 return (obj is InputStreamImpl) &&
313                                         BaseStream.Equals (((InputStreamImpl) obj).BaseStream);
314                         }
315
316                         public override int GetHashCode () {
317                                 return _stream.GetHashCode ();
318                         }
319
320                         public Stream BaseStream {
321                                 get { return _stream; }
322                         }
323                 }
324
325                 #endregion
326
327                 #region OutputStreamImpl
328
329                 sealed class OutputStreamImpl : OutputStream
330                 {
331                         readonly Stream _stream;
332
333                         public OutputStreamImpl (Stream stream) {
334                                 _stream = stream;
335                         }
336
337                         public override void close () {
338                                 BaseStream.Close ();
339                         }
340
341                         public override void flush () {
342                                 BaseStream.Flush ();
343                         }
344
345                         public override void write (int b) {
346                                 BaseStream.WriteByte ((byte) (b & 0xFF));
347                         }
348
349                         public override void write (sbyte [] b, int off, int len) {
350                                 BaseStream.Write ((byte []) TypeUtils.ToByteArray (b), off, len);
351                         }
352
353                         public override bool Equals (object obj) {
354                                 return (obj is OutputStreamImpl) &&
355                                         BaseStream.Equals (((OutputStreamImpl) obj).BaseStream);
356                         }
357
358                         public override int GetHashCode () {
359                                 return _stream.GetHashCode ();
360                         }
361
362                         public Stream BaseStream {
363                                 get { return _stream; }
364                         }
365                 }
366
367                 #endregion
368         }
369 }