2002-08-01 Miguel de Icaza <miguel@ximian.com>
[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 //
8 // (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
9 //
10
11 using System.Threading;
12
13 namespace System.IO
14 {
15         [Serializable]
16         public abstract class Stream : MarshalByRefObject, IDisposable
17         {
18                 public static readonly Stream Null;
19
20                 static Stream ()
21                 {
22                         Null = new NullStream ();
23                 }
24
25                 protected Stream ()
26                 {
27                 }
28
29                 public abstract bool CanRead
30                 {
31                         get;
32                 }
33
34                 public abstract bool CanSeek
35                 {
36                         get;
37                 }
38
39                 public abstract bool CanWrite
40                 {
41                         get;
42                 }
43
44                 public abstract long Length
45                 {
46                         get;
47                 }
48
49                 public abstract long Position
50                 {
51                         get;
52                         set;
53                 }
54
55
56                 public virtual void Close ()
57                 {
58                         Flush ();
59                 }
60
61                 void IDisposable.Dispose ()
62                 {
63                         Close ();
64                 }
65
66                 protected virtual WaitHandle CreateWaitHandle()
67                 {
68                         return new ManualResetEvent (false);
69                 }
70                 
71                 public abstract void Flush ();
72
73                 public abstract int Read (byte[] buffer,
74                                           int offset,
75                                           int count);
76
77                 public virtual int ReadByte ()
78                 {
79                         byte[] buffer = new byte [1];
80
81                         if (Read (buffer, 0, 1) == 1)
82                                 return buffer [0];
83                         
84                         return -1;
85                 }
86
87                 public abstract long Seek (long offset,
88                                            SeekOrigin origin);
89
90                 public abstract void SetLength (long value);
91
92                 public abstract void Write (byte[] buffer,
93                                             int offset,
94                                             int count);
95
96                 public virtual void WriteByte (byte value)
97                 {
98                         byte[] buffer = new byte [1];
99
100                         buffer [0] = value;
101
102                         Write (buffer, 0, 1);
103                 }
104
105                 delegate int ReadDelegate (byte [] buffer, int offset, int count);
106
107                 public virtual IAsyncResult
108                 BeginRead (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
109                 {
110                         if (!CanRead)
111                                 throw new NotSupportedException ("This stream does not support reading");
112
113                         SyncReadResult srr = new SyncReadResult (state);
114                         try
115                         {
116                                 srr.Complete (Read (buffer, offset, count));
117                         }
118                         catch (IOException e)
119                         {
120                                 srr._exception = e;
121                         }
122
123                         if (cback != null)
124                                 cback (srr);
125
126                         return srr;
127                 }
128
129                 public virtual IAsyncResult
130                 BeginWrite (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
131                 {
132                         if (!CanWrite)
133                                 throw new NotSupportedException ("This stream does not support reading");
134
135                         SyncWriteResult swr = new SyncWriteResult (state);
136                         try
137                         {
138                                 Write (buffer, offset, count);
139                                 swr.Complete ();
140                         }
141                         catch (IOException e)
142                         {
143                                 swr._exception = e;
144                         }
145
146                         if (cback != null)
147                                 cback (swr);
148
149                         return swr;
150                 }
151                 
152                 public virtual int EndRead (IAsyncResult async_result)
153                 {
154                         if (async_result == null)
155                                 throw new ArgumentNullException ("async_result");
156                         SyncReadResult srr = async_result as SyncReadResult;
157                         if (srr == null)
158                                 throw new ArgumentException ("async_result is invalid");
159                         if (srr._fEndCalled)
160                                 throw new InvalidOperationException ("EndRead called twice");
161                         srr._fEndCalled = true;
162                         if (srr._exception != null)
163                                 throw srr._exception;
164                         return srr._cbRead;
165                 }
166
167                 public virtual void EndWrite (IAsyncResult async_result)
168                 {
169                         if (async_result == null)
170                                 throw new ArgumentNullException ("async_result");
171                         SyncWriteResult swr = async_result as SyncWriteResult;
172                         if (swr == null)
173                                 throw new ArgumentException ("async_result is invalid");
174                         if (swr._fEndCalled)
175                                 throw new InvalidOperationException ("EndRead called twice");
176                         swr._fEndCalled = true;
177                         if (swr._exception != null)
178                                 throw swr._exception;
179                 }
180
181                 // this class implements the synchronous IASyncResult for the obove methods
182                 private class SyncResult : IAsyncResult
183                 {
184                         object _objState;               // client-supplied state
185                         bool _fComplete;                // if the IO operation completed successfully
186                         ManualResetEvent _hWait;                // the wait event
187                         public bool _fEndCalled;                // true iff the End method was called already
188                         public Exception _exception;    // holds any exception throw during IO operation
189
190                         public SyncResult (object objState)
191                         {
192                                 _objState = objState;
193                                 _hWait = new ManualResetEvent (false);
194                         }
195
196                         public void Complete ()
197                         {
198                                 _fComplete = true;
199                                 _hWait.Set ();
200                         }
201
202                         // IAsyncResult members
203                         object IAsyncResult.AsyncState
204                         {
205                                 get { return _objState; }
206                         }
207
208                         WaitHandle IAsyncResult.AsyncWaitHandle
209                         {
210                                 get { return _hWait; }
211                         }
212
213                         bool IAsyncResult.CompletedSynchronously
214                         {
215                                 get { return true; }
216                         }
217
218                         bool IAsyncResult.IsCompleted
219                         {
220                                 get { return _fComplete; }
221                         }
222                 }
223                 private class SyncReadResult : SyncResult
224                 {
225                         public int _cbRead;             // the number of bytes read
226
227                         public SyncReadResult (object objState) : base (objState) {}
228
229                         public void Complete (int cbRead)
230                         {
231                                 _cbRead = cbRead;
232                                 Complete ();
233                         }
234                 }
235                 private class SyncWriteResult : SyncResult
236                 {
237                         public SyncWriteResult (object objState) : base (objState) {}
238                 }
239         }
240
241         class NullStream : Stream
242         {
243                 public override bool CanRead
244                 {
245                         get {
246                                 return true;
247                         }
248                 }
249
250                 public override bool CanSeek
251                 {
252                         get {
253                                 return true;
254                         }
255                 }
256
257                 public override bool CanWrite
258                 {
259                         get {
260                                 return true;
261                         }
262                 }
263
264                 public override long Length
265                 {
266                         get {
267                                 return 0;
268                         }
269                 }
270
271                 public override long Position
272                 {
273                         get {
274                                 return 0;
275                         }
276                         set {
277                         }
278                 }
279
280                 public override void Flush ()
281                 {
282                 }
283
284                 public override int Read (byte[] buffer,
285                                           int offset,
286                                           int count)
287                 {
288                         return 0;
289                 }
290
291                 public override int ReadByte ()
292                 {
293                         return -1;
294                 }
295
296                 public override long Seek (long offset,
297                                            SeekOrigin origin)
298                 {
299                         return 0;
300                 }
301
302                 public override void SetLength (long value)
303                 {
304                 }
305
306                 public override void Write (byte[] buffer,
307                                             int offset,
308                                             int count)
309                 {
310                 }
311
312                 public override void WriteByte (byte value)
313                 {
314                 }
315         }
316 }
317
318
319
320
321
322
323