Merge pull request #3715 from kumpera/fix-44707
[mono.git] / mcs / class / WindowsBase / ZipSharp / ZipStream.cs
1 // ZipStream.cs created with MonoDevelop
2 // User: alan at 15:16 20/10/2008
3 //
4 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
5 //
6
7 using System;
8 using System.IO;
9 using System.Runtime.InteropServices;
10
11 namespace zipsharp
12 {
13         class ZipStream : Stream
14         {
15                 const int ZLIB_FILEFUNC_SEEK_CUR = 1;
16                 const int ZLIB_FILEFUNC_SEEK_END = 2;
17                 const int ZLIB_FILEFUNC_SEEK_SET = 0;
18                 
19                 bool canRead;
20                 bool canSeek;
21                 bool canWrite;
22                 
23                 public override bool CanRead {
24                         get { return canRead; }
25                 }
26
27                 public override bool CanSeek {
28                         get { return canSeek; }
29                 }
30
31                 public override bool CanWrite {
32                         get { return canWrite; }
33                 }
34
35                 public override bool CanTimeout {
36                         get { return false; }
37                 }
38                 
39                 private Stream DataStream {
40                         get; set;
41                 }
42
43                 public ZlibFileFuncDef32 IOFunctions32 {
44                         get; set;
45                 }
46
47                 public ZlibFileFuncDef64 IOFunctions64 {
48                         get; set;
49                 }
50
51                 public override long Length {
52                         get { return DataStream.Length; }
53                 }
54
55                 bool OwnsStream {
56                         get; set;
57                 }
58                 
59                 public override long Position {
60                         get { return DataStream.Position; }
61                         set { DataStream.Position = value; }
62                 }
63                 
64                 public ZipStream (Stream dataStream, bool ownsStream)
65                 {
66                         // FIXME: Not necessarily true
67                         canRead = true;
68                         canSeek = true;
69                         canWrite = true;
70
71                         DataStream = dataStream;
72                         OwnsStream = ownsStream;
73                         
74                         ZlibFileFuncDef32 f32 = new ZlibFileFuncDef32 ();
75                         f32.opaque = IntPtr.Zero;
76                         f32.zclose_file = CloseFile_Native;
77                         f32.zerror_file = TestError_Native;
78                         f32.zopen_file = OpenFile_Native;
79                         f32.zread_file = ReadFile_Native32;
80                         f32.zseek_file = SeekFile_Native32;
81                         f32.ztell_file = TellFile_Native32;
82                         f32.zwrite_file = WriteFile_Native32;
83                         IOFunctions32 = f32;
84
85                         ZlibFileFuncDef64 f64 = new ZlibFileFuncDef64 ();
86                         f64.opaque = IntPtr.Zero;
87                         f64.zclose_file = CloseFile_Native;
88                         f64.zerror_file = TestError_Native;
89                         f64.zopen_file = OpenFile_Native;
90                         f64.zread_file = ReadFile_Native64;
91                         f64.zseek_file = SeekFile_Native64;
92                         f64.ztell_file = TellFile_Native64;
93                         f64.zwrite_file = WriteFile_Native64;
94                         IOFunctions64 = f64;
95                 }
96
97                 protected override void Dispose(bool disposing)
98                 {
99                         if (!disposing)
100                                 return;
101
102                         DataStream.Flush ();
103                         if (OwnsStream)
104                                 DataStream.Dispose ();
105                 }
106
107                 public override void Flush()
108                 {
109                         DataStream.Flush ();
110                 }
111                 
112                 public override int Read(byte[] buffer, int offset, int count)
113                 {
114                         return DataStream.Read (buffer, offset, count);
115                 }
116
117                 public override long Seek(long offset, SeekOrigin origin)
118                 {
119                         DataStream.Seek (offset, origin);
120                         return DataStream.Position;
121                 }
122
123                 public override void SetLength(long value)
124                 {
125                         DataStream.SetLength (value);
126                 }
127
128                 public override void Write(byte[] buffer, int offset, int count)
129                 {
130                         DataStream.Write (buffer, offset, count);
131                         Flush ();
132                 }
133
134                 int CloseFile_Native (IntPtr opaque, IntPtr stream)
135                 {
136                         Close ();
137                         return 0;
138                 }
139                 
140                 IntPtr OpenFile_Native (IntPtr opaque, string filename, int mode)
141                 {
142                         // always success. The stream is opened in managed code
143                         return new IntPtr (1);
144                 }
145
146                 unsafe uint ReadFile_Native32 (IntPtr opaque, IntPtr stream, IntPtr buffer, uint size)
147                 {
148                         return (uint) ReadFile_Native64 (opaque, stream, buffer, size);
149                 }
150
151                 unsafe ulong ReadFile_Native64 (IntPtr opaque, IntPtr stream, IntPtr buffer, ulong size)
152                 {
153                         int count = (int) size;
154                         byte[] b = new byte[count];
155                         int read;
156                         
157                         try {
158                                 read = Math.Max (0, Read (b, 0, count));
159                                 byte* ptrBuffer = (byte*) buffer.ToPointer ();
160                                 for (int i = 0; i < count && i < read; i ++)
161                                         ptrBuffer[i] = b[i];
162                         } catch {
163                                 read = -1;
164                         }
165
166                         return (ulong) read;
167                 }
168
169                 int SeekFile_Native32 (IntPtr opaque, IntPtr stream, uint offset, int origin)
170                 {
171                         return (int) SeekFile_Native64 (opaque, stream, offset, origin);
172                 }
173
174                 long SeekFile_Native64 (IntPtr opaque, IntPtr stream, ulong offset, int origin)
175                 {
176                         SeekOrigin seek;
177                         if (origin == ZipStream.ZLIB_FILEFUNC_SEEK_CUR)
178                                 seek = SeekOrigin.Current;
179                         else if (origin == ZLIB_FILEFUNC_SEEK_END)
180                                 seek = SeekOrigin.End;
181                         else if (origin == ZLIB_FILEFUNC_SEEK_SET)
182                                 seek = SeekOrigin.Begin;
183                         else
184                                 return -1;
185
186                         Seek ((long) offset, seek);
187                         
188                         return 0;
189                 }
190
191                 int TellFile_Native32 (IntPtr opaque, IntPtr stream)
192                 {
193                         return (int) TellFile_Native64 (opaque, stream);
194                 }
195
196                 long TellFile_Native64 (IntPtr opaque, IntPtr stream)
197                 {
198                         return Position;
199                 }
200
201                 int TestError_Native (IntPtr opaque, IntPtr stream)
202                 {
203                         // No errors here.
204                         return 0;
205                 }
206
207                 unsafe uint WriteFile_Native32 (IntPtr opaque, IntPtr stream, IntPtr buffer, /* ulong */ uint size)
208                 {
209                         return (uint) WriteFile_Native64 (opaque, stream, buffer, size);
210                 }
211
212                 unsafe ulong WriteFile_Native64 (IntPtr opaque, IntPtr stream, IntPtr buffer, /* ulong */ ulong size)
213                 {
214                         int count = (int) size;
215                         byte[] b = new byte[count];
216
217                         byte* ptrBuffer = (byte*) buffer.ToPointer ();
218                         for (int i = 0; i < count; i ++)
219                                 b[i] = ptrBuffer[i];
220
221                         try {
222                                 Write (b, 0, count);
223                         } catch {
224                                 
225                         }
226
227                         return (ulong) count;
228                 }
229         }
230 }