5 // Dietmar Maurer (dietmar@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // Marek Safar (marek.safar@gmail.com)
10 // (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 // (c) 2004 Novell, Inc. (http://www.novell.com)
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Threading;
35 using System.Runtime.Remoting.Messaging;
36 using System.Runtime.InteropServices;
38 using System.Threading.Tasks;
46 public abstract class Stream : IDisposable
48 public abstract class Stream : MarshalByRefObject, IDisposable
51 public static readonly Stream Null = new NullStream ();
53 Func<byte[], int, int, int> async_read;
54 Action<byte[], int, int> async_write;
55 AutoResetEvent async_event;
61 public abstract bool CanRead
66 public abstract bool CanSeek
71 public abstract bool CanWrite
77 public virtual bool CanTimeout {
83 public abstract long Length
88 public abstract long Position
95 public void Dispose ()
100 protected virtual void Dispose (bool disposing)
102 if (async_event != null && disposing) {
103 async_event.Close ();
108 public virtual void Close ()
111 GC.SuppressFinalize (this);
115 public virtual int ReadTimeout {
117 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
120 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
125 public virtual int WriteTimeout {
127 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
130 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
134 public static Stream Synchronized (Stream stream)
136 return new SynchronizedStream (stream);
139 [Obsolete ("CreateWaitHandle is due for removal. Use \"new ManualResetEvent(false)\" instead.")]
140 protected virtual WaitHandle CreateWaitHandle()
142 return new ManualResetEvent (false);
145 public abstract void Flush ();
147 public abstract int Read ([In,Out] byte[] buffer, int offset, int count);
149 public virtual int ReadByte ()
151 byte[] buffer = new byte [1];
153 if (Read (buffer, 0, 1) == 1)
159 public abstract long Seek (long offset, SeekOrigin origin);
161 public abstract void SetLength (long value);
163 public abstract void Write (byte[] buffer, int offset, int count);
165 public virtual void WriteByte (byte value)
167 byte[] buffer = new byte [1];
171 Write (buffer, 0, 1);
174 public virtual IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
177 throw new NotSupportedException ("This stream does not support reading");
179 if (async_event == null) {
181 if (async_event == null)
182 async_event = new AutoResetEvent (true);
186 async_event.WaitOne ();
188 return async_read.BeginInvoke (buffer, offset, count, callback, state);
191 public virtual IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
194 throw new NotSupportedException ("This stream does not support writing");
196 if (async_event == null) {
198 if (async_event == null)
199 async_event = new AutoResetEvent (true);
203 async_event.WaitOne ();
205 return async_write.BeginInvoke (buffer, offset, count, callback, state);
208 public virtual int EndRead (IAsyncResult asyncResult)
210 if (asyncResult == null)
211 throw new ArgumentNullException ("asyncResult");
213 if (async_read == null)
214 throw new ArgumentException ("EndRead cannot be called multiple times");
217 return async_read.EndInvoke (asyncResult);
224 public virtual void EndWrite (IAsyncResult asyncResult)
226 if (asyncResult == null)
227 throw new ArgumentNullException ("asyncResult");
229 if (async_write == null)
230 throw new ArgumentException ("EndWrite cannot be called multiple times");
233 async_write.EndInvoke (asyncResult);
240 #if MOONLIGHT || NET_4_0 || MOBILE
241 public void CopyTo (Stream destination)
243 CopyTo (destination, 16*1024);
246 public void CopyTo (Stream destination, int bufferSize)
248 if (destination == null)
249 throw new ArgumentNullException ("destination");
251 throw new NotSupportedException ("This stream does not support reading");
252 if (!destination.CanWrite)
253 throw new NotSupportedException ("This destination stream does not support writing");
255 throw new ArgumentOutOfRangeException ("bufferSize");
257 var buffer = new byte [bufferSize];
259 while ((nread = Read (buffer, 0, bufferSize)) != 0)
260 destination.Write (buffer, 0, nread);
264 [ObsoleteAttribute("Do not call or override this method")]
266 protected virtual void ObjectInvariant ()
273 public Task CopyToAsync (Stream destination)
275 return CopyToAsync (destination, 16 * 1024, CancellationToken.None);
278 public Task CopyToAsync (Stream destination, int bufferSize)
280 return CopyToAsync (destination, bufferSize, CancellationToken.None);
283 public virtual Task CopyToAsync (Stream destination, int bufferSize, CancellationToken cancellationToken)
285 if (destination == null)
286 throw new ArgumentNullException ("destination");
288 throw new NotSupportedException ("This stream does not support reading");
289 if (!destination.CanWrite)
290 throw new NotSupportedException ("This destination stream does not support writing");
292 throw new ArgumentOutOfRangeException ("bufferSize");
294 if (cancellationToken.IsCancellationRequested)
295 return TaskConstants.Canceled;
297 return CopyToAsync (destination, new byte[bufferSize], cancellationToken);
300 async Task CopyToAsync (Stream destination, byte[] buffer, CancellationToken cancellationToken)
303 while ((nread = await ReadAsync (buffer, 0, buffer.Length).ConfigureAwait (false)) != 0)
304 await destination.WriteAsync (buffer, 0, nread, cancellationToken).ConfigureAwait (false);
307 public Task FlushAsync ()
309 return FlushAsync (CancellationToken.None);
312 public virtual Task FlushAsync (CancellationToken cancellationToken)
314 if (cancellationToken.IsCancellationRequested)
315 return TaskConstants.Canceled;
317 return Task.Factory.StartNew (l => ((Stream) l).Flush (), this, cancellationToken);
320 public Task<int> ReadAsync (byte[] buffer, int offset, int count)
322 return ReadAsync (buffer, offset, count, CancellationToken.None);
325 public virtual Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
327 if (cancellationToken.IsCancellationRequested)
328 return TaskConstants<int>.Canceled;
330 return Task<int>.Factory.FromAsync (BeginRead, EndRead, buffer, offset, count, null);
333 public Task WriteAsync (byte[] buffer, int offset, int count)
335 return WriteAsync (buffer, offset, count, CancellationToken.None);
338 public virtual Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
340 return Task.Factory.FromAsync (BeginWrite, EndWrite, buffer, offset, count, null);
345 class NullStream : Stream
347 public override bool CanRead
354 public override bool CanSeek
361 public override bool CanWrite
368 public override long Length
375 public override long Position
384 public override void Flush ()
388 public override int Read (byte[] buffer, int offset, int count)
393 public override int ReadByte ()
398 public override long Seek (long offset, SeekOrigin origin)
403 public override void SetLength (long value)
407 public override void Write (byte[] buffer, int offset, int count)
411 public override void WriteByte (byte value)
416 class SynchronizedStream : Stream {
420 internal SynchronizedStream (Stream source)
422 this.source = source;
423 slock = new object ();
426 public override bool CanRead
430 return source.CanRead;
434 public override bool CanSeek
438 return source.CanSeek;
442 public override bool CanWrite
446 return source.CanWrite;
450 public override long Length
454 return source.Length;
458 public override long Position
462 return source.Position;
466 source.Position = value;
470 public override void Flush ()
476 public override int Read (byte[] buffer, int offset, int count)
479 return source.Read (buffer, offset, count);
482 public override int ReadByte ()
485 return source.ReadByte ();
488 public override long Seek (long offset, SeekOrigin origin)
491 return source.Seek (offset, origin);
494 public override void SetLength (long value)
497 source.SetLength (value);
500 public override void Write (byte[] buffer, int offset, int count)
503 source.Write (buffer, offset, count);
506 public override void WriteByte (byte value)
509 source.WriteByte (value);