Registry server LDB backend: Don't make copies of the same type
[tprouty/samba.git] / lib / zlib / contrib / dotzlib / DotZLib / GZipStream.cs
1 //\r
2 // © Copyright Henrik Ravn 2004\r
3 //\r
4 // Use, modification and distribution are subject to the Boost Software License, Version 1.0. \r
5 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
6 //\r
7 \r
8 using System;\r
9 using System.IO;\r
10 using System.Runtime.InteropServices;\r
11 \r
12 namespace DotZLib\r
13 {\r
14         /// <summary>\r
15         /// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format.\r
16         /// </summary>\r
17         public class GZipStream : Stream, IDisposable\r
18         {\r
19         #region Dll Imports\r
20         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]\r
21         private static extern IntPtr gzopen(string name, string mode);\r
22 \r
23         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
24         private static extern int gzclose(IntPtr gzFile);\r
25 \r
26         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
27         private static extern int gzwrite(IntPtr gzFile, int data, int length);\r
28 \r
29         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
30         private static extern int gzread(IntPtr gzFile, int data, int length);\r
31 \r
32         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
33         private static extern int gzgetc(IntPtr gzFile);\r
34 \r
35         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
36         private static extern int gzputc(IntPtr gzFile, int c);\r
37 \r
38         #endregion\r
39 \r
40         #region Private data\r
41         private IntPtr _gzFile;\r
42         private bool _isDisposed = false;\r
43         private bool _isWriting;\r
44         #endregion\r
45 \r
46         #region Constructors\r
47         /// <summary>\r
48         /// Creates a new file as a writeable GZipStream\r
49         /// </summary>\r
50         /// <param name="fileName">The name of the compressed file to create</param>\r
51         /// <param name="level">The compression level to use when adding data</param>\r
52         /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>\r
53                 public GZipStream(string fileName, CompressLevel level)\r
54                 {\r
55             _isWriting = true;\r
56             _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level));\r
57             if (_gzFile == IntPtr.Zero)\r
58                 throw new ZLibException(-1, "Could not open " + fileName);\r
59                 }\r
60 \r
61         /// <summary>\r
62         /// Opens an existing file as a readable GZipStream\r
63         /// </summary>\r
64         /// <param name="fileName">The name of the file to open</param>\r
65         /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>\r
66         public GZipStream(string fileName)\r
67         {\r
68             _isWriting = false;\r
69             _gzFile = gzopen(fileName, "rb");\r
70             if (_gzFile == IntPtr.Zero)\r
71                 throw new ZLibException(-1, "Could not open " + fileName);\r
72 \r
73         }\r
74         #endregion\r
75 \r
76         #region Access properties\r
77         /// <summary>\r
78         /// Returns true of this stream can be read from, false otherwise\r
79         /// </summary>\r
80         public override bool CanRead\r
81         {\r
82             get\r
83             {\r
84                 return !_isWriting;\r
85             }\r
86         }\r
87     \r
88 \r
89         /// <summary>\r
90         /// Returns false.\r
91         /// </summary>\r
92         public override bool CanSeek\r
93         {\r
94             get\r
95             {\r
96                 return false;\r
97             }\r
98         }\r
99     \r
100         /// <summary>\r
101         /// Returns true if this tsream is writeable, false otherwise\r
102         /// </summary>\r
103         public override bool CanWrite\r
104         {\r
105             get\r
106             {\r
107                 return _isWriting;\r
108             }\r
109         }\r
110         #endregion\r
111     \r
112         #region Destructor & IDispose stuff\r
113 \r
114         /// <summary>\r
115         /// Destroys this instance\r
116         /// </summary>\r
117         ~GZipStream()\r
118         {\r
119             cleanUp(false);\r
120         }\r
121 \r
122         /// <summary>\r
123         /// Closes the external file handle\r
124         /// </summary>\r
125         public void Dispose()\r
126         {\r
127             cleanUp(true);\r
128         }\r
129 \r
130         // Does the actual closing of the file handle.\r
131         private void cleanUp(bool isDisposing)\r
132         {\r
133             if (!_isDisposed)\r
134             {\r
135                 gzclose(_gzFile);\r
136                 _isDisposed = true;\r
137             }\r
138         }\r
139         #endregion\r
140     \r
141         #region Basic reading and writing\r
142         /// <summary>\r
143         /// Attempts to read a number of bytes from the stream.\r
144         /// </summary>\r
145         /// <param name="buffer">The destination data buffer</param>\r
146         /// <param name="offset">The index of the first destination byte in <c>buffer</c></param>\r
147         /// <param name="count">The number of bytes requested</param>\r
148         /// <returns>The number of bytes read</returns>\r
149         /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>\r
150         /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>\r
151         /// <exception cref="ArgumentException">If <c>offset</c>  + <c>count</c> is &gt; buffer.Length</exception>\r
152         /// <exception cref="NotSupportedException">If this stream is not readable.</exception>\r
153         /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
154         public override int Read(byte[] buffer, int offset, int count)\r
155         {\r
156             if (!CanRead) throw new NotSupportedException();\r
157             if (buffer == null) throw new ArgumentNullException();\r
158             if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();\r
159             if ((offset+count) > buffer.Length) throw new ArgumentException();\r
160             if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
161 \r
162             GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);\r
163             int result;\r
164             try\r
165             {\r
166                 result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);\r
167                 if (result < 0)\r
168                     throw new IOException();\r
169             }\r
170             finally\r
171             {\r
172                 h.Free();\r
173             }\r
174             return result;\r
175         }\r
176 \r
177         /// <summary>\r
178         /// Attempts to read a single byte from the stream.\r
179         /// </summary>\r
180         /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns>\r
181         public override int ReadByte()\r
182         {\r
183             if (!CanRead) throw new NotSupportedException();\r
184             if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
185             return gzgetc(_gzFile);\r
186         }\r
187 \r
188         /// <summary>\r
189         /// Writes a number of bytes to the stream\r
190         /// </summary>\r
191         /// <param name="buffer"></param>\r
192         /// <param name="offset"></param>\r
193         /// <param name="count"></param>\r
194         /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>\r
195         /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>\r
196         /// <exception cref="ArgumentException">If <c>offset</c>  + <c>count</c> is &gt; buffer.Length</exception>\r
197         /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>\r
198         /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
199         public override void Write(byte[] buffer, int offset, int count)\r
200         {\r
201             if (!CanWrite) throw new NotSupportedException();\r
202             if (buffer == null) throw new ArgumentNullException();\r
203             if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();\r
204             if ((offset+count) > buffer.Length) throw new ArgumentException();\r
205             if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
206 \r
207             GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);\r
208             try\r
209             {\r
210                 int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);\r
211                 if (result < 0)\r
212                     throw new IOException();\r
213             }\r
214             finally\r
215             {\r
216                 h.Free();\r
217             }\r
218         }\r
219 \r
220         /// <summary>\r
221         /// Writes a single byte to the stream\r
222         /// </summary>\r
223         /// <param name="value">The byte to add to the stream.</param>\r
224         /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>\r
225         /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
226         public override void WriteByte(byte value)\r
227         {\r
228             if (!CanWrite) throw new NotSupportedException();\r
229             if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
230 \r
231             int result = gzputc(_gzFile, (int)value);\r
232             if (result < 0)\r
233                 throw new IOException();\r
234         }\r
235         #endregion\r
236 \r
237         #region Position & length stuff\r
238         /// <summary>\r
239         /// Not supported.\r
240         /// </summary>\r
241         /// <param name="value"></param>\r
242         /// <exception cref="NotSupportedException">Always thrown</exception>\r
243         public override void SetLength(long value)\r
244         {\r
245             throw new NotSupportedException();\r
246         }\r
247     \r
248         /// <summary>\r
249         ///  Not suppported.\r
250         /// </summary>\r
251         /// <param name="offset"></param>\r
252         /// <param name="origin"></param>\r
253         /// <returns></returns>\r
254         /// <exception cref="NotSupportedException">Always thrown</exception>\r
255         public override long Seek(long offset, SeekOrigin origin)\r
256         {\r
257             throw new NotSupportedException();\r
258         }\r
259     \r
260         /// <summary>\r
261         /// Flushes the <c>GZipStream</c>.\r
262         /// </summary>\r
263         /// <remarks>In this implementation, this method does nothing. This is because excessive\r
264         /// flushing may degrade the achievable compression rates.</remarks>\r
265         public override void Flush()\r
266         {\r
267             // left empty on purpose\r
268         }\r
269     \r
270         /// <summary>\r
271         /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.\r
272         /// </summary>\r
273         /// <remarks>In this implementation this property is not supported</remarks>\r
274         /// <exception cref="NotSupportedException">Always thrown</exception>\r
275         public override long Position\r
276         {\r
277             get\r
278             {\r
279                 throw new NotSupportedException();\r
280             }\r
281             set\r
282             {\r
283                 throw new NotSupportedException();\r
284             }\r
285         }\r
286     \r
287         /// <summary>\r
288         /// Gets the size of the stream. Not suppported.\r
289         /// </summary>\r
290         /// <remarks>In this implementation this property is not supported</remarks>\r
291         /// <exception cref="NotSupportedException">Always thrown</exception>\r
292         public override long Length\r
293         {\r
294             get\r
295             {\r
296                 throw new NotSupportedException();\r
297             }\r
298         }\r
299         #endregion\r
300     }\r
301 }\r