2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.IO / Stream.cs
1 //
2 // System.IO/Stream.cs
3 //
4 // Authors:
5 //   Dietmar Maurer (dietmar@ximian.com)
6 //   Miguel de Icaza (miguel@ximian.com)
7 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 // (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
11 //
12
13 //
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System.Threading;
37 using System.Runtime.Remoting.Messaging;
38 using System.Runtime.InteropServices;
39
40 namespace System.IO
41 {
42         [Serializable]
43         public abstract class Stream : MarshalByRefObject, IDisposable
44         {
45                 public static readonly Stream Null = new NullStream ();
46
47                 protected Stream ()
48                 {
49                 }
50
51                 public abstract bool CanRead
52                 {
53                         get;
54                 }
55
56                 public abstract bool CanSeek
57                 {
58                         get;
59                 }
60
61                 public abstract bool CanWrite
62                 {
63                         get;
64                 }
65
66                 public abstract long Length
67                 {
68                         get;
69                 }
70
71                 public abstract long Position
72                 {
73                         get;
74                         set;
75                 }
76
77
78                 public virtual void Close ()
79                 {
80                 }
81
82                 void IDisposable.Dispose ()
83                 {
84                         Close ();
85                 }
86
87                 protected virtual WaitHandle CreateWaitHandle()
88                 {
89                         return new ManualResetEvent (false);
90                 }
91                 
92                 public abstract void Flush ();
93
94                 public abstract int Read ([In,Out] byte[] buffer, int offset, int count);
95
96                 public virtual int ReadByte ()
97                 {
98                         byte[] buffer = new byte [1];
99
100                         if (Read (buffer, 0, 1) == 1)
101                                 return buffer [0];
102                         
103                         return -1;
104                 }
105
106                 public abstract long Seek (long offset, SeekOrigin origin);
107
108                 public abstract void SetLength (long value);
109
110                 public abstract void Write (byte[] buffer, int offset, int count);
111
112                 public virtual void WriteByte (byte value)
113                 {
114                         byte[] buffer = new byte [1];
115
116                         buffer [0] = value;
117
118                         Write (buffer, 0, 1);
119                 }
120
121                 public virtual IAsyncResult
122                 BeginRead (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
123                 {
124                         if (!CanRead)
125                                 throw new NotSupportedException ("This stream does not support reading");
126
127                         // Creating a class derived from Stream that doesn't override BeginRead
128                         // shows that it actually calls Read and does everything synchronously.
129                         // Just put this in the Read override:
130                         //      Console.WriteLine ("Read");
131                         //      Console.WriteLine (Environment.StackTrace);
132                         //      Thread.Sleep (10000);
133                         //      return 10;
134
135                         StreamAsyncResult result = new StreamAsyncResult (state);
136                         try {
137                                 int nbytes = Read (buffer, offset, count);
138                                 result.SetComplete (null, nbytes);
139                         } catch (Exception e) {
140                                 result.SetComplete (e, 0);
141                         }
142
143                         if (cback != null)
144                                 cback (result);
145
146                         return result;
147                 }
148
149                 delegate void WriteDelegate (byte [] buffer, int offset, int count);
150
151                 public virtual IAsyncResult
152                 BeginWrite (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
153                 {
154                         if (!CanWrite)
155                                 throw new NotSupportedException ("This stream does not support writing");
156         
157                         // Creating a class derived from Stream that doesn't override BeginWrite
158                         // shows that it actually calls Write and does everything synchronously except
159                         // when invoking the callback, which is done from the ThreadPool.
160                         // Just put this in the Write override:
161                         //      Console.WriteLine ("Write");
162                         //      Console.WriteLine (Environment.StackTrace);
163                         //      Thread.Sleep (10000);
164
165                         StreamAsyncResult result = new StreamAsyncResult (state);
166                         try {
167                                 Write (buffer, offset, count);
168                                 result.SetComplete (null);
169                         } catch (Exception e) {
170                                 result.SetComplete (e);
171                         }
172
173                         if (cback != null)
174                                 cback.BeginInvoke (result, null, null);
175
176                         return result;
177                 }
178                 
179                 public virtual int EndRead (IAsyncResult async_result)
180                 {
181                         if (async_result == null)
182                                 throw new ArgumentNullException ("async_result");
183
184                         StreamAsyncResult result = async_result as StreamAsyncResult;
185                         if (result == null || result.NBytes == -1)
186                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
187
188                         if (result.Done)
189                                 throw new InvalidOperationException ("EndRead already called.");
190
191                         result.Done = true;
192                         if (result.Exception != null)
193                                 throw result.Exception;
194
195                         return result.NBytes;
196                 }
197
198                 public virtual void EndWrite (IAsyncResult async_result)
199                 {
200                         if (async_result == null)
201                                 throw new ArgumentNullException ("async_result");
202
203                         StreamAsyncResult result = async_result as StreamAsyncResult;
204                         if (result == null || result.NBytes != -1)
205                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
206
207                         if (result.Done)
208                                 throw new InvalidOperationException ("EndWrite already called.");
209
210                         result.Done = true;
211                         if (result.Exception != null)
212                                 throw result.Exception;
213                 }
214         }
215
216         class NullStream : Stream
217         {
218                 public override bool CanRead
219                 {
220                         get {
221                                 return true;
222                         }
223                 }
224
225                 public override bool CanSeek
226                 {
227                         get {
228                                 return true;
229                         }
230                 }
231
232                 public override bool CanWrite
233                 {
234                         get {
235                                 return true;
236                         }
237                 }
238
239                 public override long Length
240                 {
241                         get {
242                                 return 0;
243                         }
244                 }
245
246                 public override long Position
247                 {
248                         get {
249                                 return 0;
250                         }
251                         set {
252                         }
253                 }
254
255                 public override void Flush ()
256                 {
257                 }
258
259                 public override int Read (byte[] buffer,
260                                           int offset,
261                                           int count)
262                 {
263                         return 0;
264                 }
265
266                 public override int ReadByte ()
267                 {
268                         return -1;
269                 }
270
271                 public override long Seek (long offset,
272                                            SeekOrigin origin)
273                 {
274                         return 0;
275                 }
276
277                 public override void SetLength (long value)
278                 {
279                 }
280
281                 public override void Write (byte[] buffer,
282                                             int offset,
283                                             int count)
284                 {
285                 }
286
287                 public override void WriteByte (byte value)
288                 {
289                 }
290         }
291 }