lalala
[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 using System.Threading;
14 using System.Runtime.Remoting.Messaging;
15 using System.Runtime.InteropServices;
16
17 namespace System.IO
18 {
19         [Serializable]
20         public abstract class Stream : MarshalByRefObject, IDisposable
21         {
22                 public static readonly Stream Null;
23
24                 static Stream ()
25                 {
26                         Null = new NullStream ();
27                 }
28
29                 protected Stream ()
30                 {
31                 }
32
33                 public abstract bool CanRead
34                 {
35                         get;
36                 }
37
38                 public abstract bool CanSeek
39                 {
40                         get;
41                 }
42
43                 public abstract bool CanWrite
44                 {
45                         get;
46                 }
47
48                 public abstract long Length
49                 {
50                         get;
51                 }
52
53                 public abstract long Position
54                 {
55                         get;
56                         set;
57                 }
58
59
60                 public virtual void Close ()
61                 {
62                         Flush ();
63                 }
64
65                 void IDisposable.Dispose ()
66                 {
67                         Close ();
68                 }
69
70                 protected virtual WaitHandle CreateWaitHandle()
71                 {
72                         return new ManualResetEvent (false);
73                 }
74                 
75                 public abstract void Flush ();
76
77                 public abstract int Read ([In,Out] byte[] buffer, int offset, int count);
78
79                 public virtual int ReadByte ()
80                 {
81                         byte[] buffer = new byte [1];
82
83                         if (Read (buffer, 0, 1) == 1)
84                                 return buffer [0];
85                         
86                         return -1;
87                 }
88
89                 public abstract long Seek (long offset, SeekOrigin origin);
90
91                 public abstract void SetLength (long value);
92
93                 public abstract void Write (byte[] buffer, int offset, int count);
94
95                 public virtual void WriteByte (byte value)
96                 {
97                         byte[] buffer = new byte [1];
98
99                         buffer [0] = value;
100
101                         Write (buffer, 0, 1);
102                 }
103
104                 public virtual IAsyncResult
105                 BeginRead (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
106                 {
107                         if (!CanRead)
108                                 throw new NotSupportedException ("This stream does not support reading");
109
110                         // Creating a class derived from Stream that doesn't override BeginRead
111                         // shows that it actually calls Read and does everything synchronously.
112                         // Just put this in the Read override:
113                         //      Console.WriteLine ("Read");
114                         //      Console.WriteLine (Environment.StackTrace);
115                         //      Thread.Sleep (10000);
116                         //      return 10;
117
118                         StreamAsyncResult result = new StreamAsyncResult (state);
119                         try {
120                                 int nbytes = Read (buffer, offset, count);
121                                 result.SetComplete (null, nbytes);
122                         } catch (Exception e) {
123                                 result.SetComplete (e, 0);
124                         }
125
126                         if (cback != null)
127                                 cback (result);
128
129                         return result;
130                 }
131
132                 delegate void WriteDelegate (byte [] buffer, int offset, int count);
133
134                 public virtual IAsyncResult
135                 BeginWrite (byte [] buffer, int offset, int count, AsyncCallback cback, object state)
136                 {
137                         if (!CanWrite)
138                                 throw new NotSupportedException ("This stream does not support writing");
139         
140                         // Creating a class derived from Stream that doesn't override BeginWrite
141                         // shows that it actually calls Write and does everything synchronously except
142                         // when invoking the callback, which is done from the ThreadPool.
143                         // Just put this in the Write override:
144                         //      Console.WriteLine ("Write");
145                         //      Console.WriteLine (Environment.StackTrace);
146                         //      Thread.Sleep (10000);
147
148                         StreamAsyncResult result = new StreamAsyncResult (state);
149                         try {
150                                 Write (buffer, offset, count);
151                                 result.SetComplete (null);
152                         } catch (Exception e) {
153                                 result.SetComplete (e);
154                         }
155
156                         if (cback != null)
157                                 cback.BeginInvoke (result, null, null);
158
159                         return result;
160                 }
161                 
162                 public virtual int EndRead (IAsyncResult async_result)
163                 {
164                         if (async_result == null)
165                                 throw new ArgumentNullException ("async_result");
166
167                         StreamAsyncResult result = async_result as StreamAsyncResult;
168                         if (result == null || result.NBytes == -1)
169                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
170
171                         if (result.Done)
172                                 throw new InvalidOperationException ("EndRead already called.");
173
174                         result.Done = true;
175                         if (result.Exception != null)
176                                 throw result.Exception;
177
178                         return result.NBytes;
179                 }
180
181                 public virtual void EndWrite (IAsyncResult async_result)
182                 {
183                         if (async_result == null)
184                                 throw new ArgumentNullException ("async_result");
185
186                         StreamAsyncResult result = async_result as StreamAsyncResult;
187                         if (result == null || result.NBytes != -1)
188                                 throw new ArgumentException ("Invalid IAsyncResult", "async_result");
189
190                         if (result.Done)
191                                 throw new InvalidOperationException ("EndWrite already called.");
192
193                         result.Done = true;
194                         if (result.Exception != null)
195                                 throw result.Exception;
196                 }
197         }
198
199         class NullStream : Stream
200         {
201                 public override bool CanRead
202                 {
203                         get {
204                                 return true;
205                         }
206                 }
207
208                 public override bool CanSeek
209                 {
210                         get {
211                                 return true;
212                         }
213                 }
214
215                 public override bool CanWrite
216                 {
217                         get {
218                                 return true;
219                         }
220                 }
221
222                 public override long Length
223                 {
224                         get {
225                                 return 0;
226                         }
227                 }
228
229                 public override long Position
230                 {
231                         get {
232                                 return 0;
233                         }
234                         set {
235                         }
236                 }
237
238                 public override void Flush ()
239                 {
240                 }
241
242                 public override int Read (byte[] buffer,
243                                           int offset,
244                                           int count)
245                 {
246                         return 0;
247                 }
248
249                 public override int ReadByte ()
250                 {
251                         return -1;
252                 }
253
254                 public override long Seek (long offset,
255                                            SeekOrigin origin)
256                 {
257                         return 0;
258                 }
259
260                 public override void SetLength (long value)
261                 {
262                 }
263
264                 public override void Write (byte[] buffer,
265                                             int offset,
266                                             int count)
267                 {
268                 }
269
270                 public override void WriteByte (byte value)
271                 {
272                 }
273         }
274 }