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 ();
54 Func<byte[], int, int, int> async_read;
56 Action<byte[], int, int> async_write;
58 AutoResetEvent async_event;
64 public abstract bool CanRead
69 public abstract bool CanSeek
74 public abstract bool CanWrite
80 public virtual bool CanTimeout {
86 public abstract long Length
91 public abstract long Position
98 public void Dispose ()
103 protected virtual void Dispose (bool disposing)
105 if (async_event != null && disposing) {
106 async_event.Close ();
111 public virtual void Close ()
114 GC.SuppressFinalize (this);
118 public virtual int ReadTimeout {
120 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
123 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
128 public virtual int WriteTimeout {
130 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
133 throw new InvalidOperationException ("Timeouts are not supported on this stream.");
137 public static Stream Synchronized (Stream stream)
139 return new SynchronizedStream (stream);
142 [Obsolete ("CreateWaitHandle is due for removal. Use \"new ManualResetEvent(false)\" instead.")]
143 protected virtual WaitHandle CreateWaitHandle()
145 return new ManualResetEvent (false);
148 public abstract void Flush ();
150 public abstract int Read ([In,Out] byte[] buffer, int offset, int count);
152 public virtual int ReadByte ()
154 byte[] buffer = new byte [1];
156 if (Read (buffer, 0, 1) == 1)
162 public abstract long Seek (long offset, SeekOrigin origin);
164 public abstract void SetLength (long value);
166 public abstract void Write (byte[] buffer, int offset, int count);
168 public virtual void WriteByte (byte value)
170 byte[] buffer = new byte [1];
174 Write (buffer, 0, 1);
177 public virtual IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
180 throw new NotSupportedException ("This stream does not support reading");
182 if (async_event == null) {
184 if (async_event == null)
185 async_event = new AutoResetEvent (true);
189 async_event.WaitOne ();
191 return async_read.BeginInvoke (buffer, offset, count, callback, state);
194 public virtual IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
197 throw new NotSupportedException ("This stream does not support writing");
199 if (async_event == null) {
201 if (async_event == null)
202 async_event = new AutoResetEvent (true);
206 async_event.WaitOne ();
208 return async_write.BeginInvoke (buffer, offset, count, callback, state);
211 public virtual int EndRead (IAsyncResult asyncResult)
213 if (asyncResult == null)
214 throw new ArgumentNullException ("asyncResult");
216 if (async_read == null)
217 throw new ArgumentException ("EndRead cannot be called multiple times");
220 return async_read.EndInvoke (asyncResult);
227 public virtual void EndWrite (IAsyncResult asyncResult)
229 if (asyncResult == null)
230 throw new ArgumentNullException ("asyncResult");
232 if (async_write == null)
233 throw new ArgumentException ("EndWrite cannot be called multiple times");
236 async_write.EndInvoke (asyncResult);
244 public void CopyTo (Stream destination)
246 CopyTo (destination, 16*1024);
249 public void CopyTo (Stream destination, int bufferSize)
251 if (destination == null)
252 throw new ArgumentNullException ("destination");
254 throw new NotSupportedException ("This stream does not support reading");
255 if (!destination.CanWrite)
256 throw new NotSupportedException ("This destination stream does not support writing");
258 throw new ArgumentOutOfRangeException ("bufferSize");
260 var buffer = new byte [bufferSize];
262 while ((nread = Read (buffer, 0, bufferSize)) != 0)
263 destination.Write (buffer, 0, nread);
267 [ObsoleteAttribute("Do not call or override this method")]
269 protected virtual void ObjectInvariant ()
276 public Task CopyToAsync (Stream destination)
278 return CopyToAsync (destination, 16 * 1024, CancellationToken.None);
281 public Task CopyToAsync (Stream destination, int bufferSize)
283 return CopyToAsync (destination, bufferSize, CancellationToken.None);
286 public virtual Task CopyToAsync (Stream destination, int bufferSize, CancellationToken cancellationToken)
288 if (destination == null)
289 throw new ArgumentNullException ("destination");
291 throw new NotSupportedException ("This stream does not support reading");
292 if (!destination.CanWrite)
293 throw new NotSupportedException ("This destination stream does not support writing");
295 throw new ArgumentOutOfRangeException ("bufferSize");
297 if (cancellationToken.IsCancellationRequested)
298 return TaskConstants.Canceled;
300 return CopyToAsync (destination, new byte[bufferSize], cancellationToken);
303 async Task CopyToAsync (Stream destination, byte[] buffer, CancellationToken cancellationToken)
306 while ((nread = await ReadAsync (buffer, 0, buffer.Length, cancellationToken).ConfigureAwait (false)) != 0)
307 await destination.WriteAsync (buffer, 0, nread, cancellationToken).ConfigureAwait (false);
310 public Task FlushAsync ()
312 return FlushAsync (CancellationToken.None);
315 public virtual Task FlushAsync (CancellationToken cancellationToken)
317 if (cancellationToken.IsCancellationRequested)
318 return TaskConstants.Canceled;
320 return Task.Factory.StartNew (l => ((Stream) l).Flush (), this, cancellationToken);
323 public Task<int> ReadAsync (byte[] buffer, int offset, int count)
325 return ReadAsync (buffer, offset, count, CancellationToken.None);
328 public virtual Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
330 if (cancellationToken.IsCancellationRequested)
331 return TaskConstants<int>.Canceled;
333 return Task<int>.Factory.FromAsync (BeginRead, EndRead, buffer, offset, count, null);
336 public Task WriteAsync (byte[] buffer, int offset, int count)
338 return WriteAsync (buffer, offset, count, CancellationToken.None);
341 public virtual Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
343 return Task.Factory.FromAsync (BeginWrite, EndWrite, buffer, offset, count, null);
348 class NullStream : Stream
350 public override bool CanRead
357 public override bool CanSeek
364 public override bool CanWrite
371 public override long Length
378 public override long Position
387 public override void Flush ()
391 public override int Read (byte[] buffer, int offset, int count)
396 public override int ReadByte ()
401 public override long Seek (long offset, SeekOrigin origin)
406 public override void SetLength (long value)
410 public override void Write (byte[] buffer, int offset, int count)
414 public override void WriteByte (byte value)
419 class SynchronizedStream : Stream {
423 internal SynchronizedStream (Stream source)
425 this.source = source;
426 slock = new object ();
429 public override bool CanRead
433 return source.CanRead;
437 public override bool CanSeek
441 return source.CanSeek;
445 public override bool CanWrite
449 return source.CanWrite;
453 public override long Length
457 return source.Length;
461 public override long Position
465 return source.Position;
469 source.Position = value;
473 public override void Flush ()
479 public override int Read (byte[] buffer, int offset, int count)
482 return source.Read (buffer, offset, count);
485 public override int ReadByte ()
488 return source.ReadByte ();
491 public override long Seek (long offset, SeekOrigin origin)
494 return source.Seek (offset, origin);
497 public override void SetLength (long value)
500 source.SetLength (value);
503 public override void Write (byte[] buffer, int offset, int count)
506 source.Write (buffer, offset, count);
509 public override void WriteByte (byte value)
512 source.WriteByte (value);