using System;
using System.IO;
using System.Runtime.Remoting;
using Developpez.Dotnet.Properties;
namespace Developpez.Dotnet.IO
{
///
/// Wraps a stream for all operations except Close and Dispose, which
/// merely flush the stream and prevent further operations from being
/// carried out using this wrapper.
///
/// Cette classe provient de la librairie MiscUtil créée par Jon Skeet
/// http://www.yoda.arachsys.com/csharp/miscutil/
///
///
internal sealed class NonClosingStreamWrapper : Stream
{
#region Members specific to this wrapper class
///
/// Creates a new instance of the class, wrapping the specified stream.
///
/// The stream to wrap. Must not be null.
/// stream is null
public NonClosingStreamWrapper(Stream stream)
{
stream.CheckArgumentNull("stream");
this.stream = stream;
}
Stream stream;
///
/// Stream wrapped by this wrapper
///
public Stream BaseStream
{
get { return stream; }
}
///
/// Whether this stream has been closed or not
///
bool closed = false;
///
/// Throws an InvalidOperationException if the wrapper is closed.
///
void CheckClosed()
{
if (closed)
{
throw new InvalidOperationException(ExceptionMessages.WrapperClosed);
}
}
#endregion
#region Overrides of Stream methods and properties
///
/// Begins an asynchronous read operation.
///
/// The buffer to read the data into.
///
/// The byte offset in buffer at which to begin writing data read from the stream.
///
/// The maximum number of bytes to read.
///
/// An optional asynchronous callback, to be called when the read is complete.
///
///
/// A user-provided object that distinguishes this particular
/// asynchronous read request from other requests.
///
///
/// An IAsyncResult that represents the asynchronous read,
/// which could still be pending.
///
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
CheckClosed();
return stream.BeginRead(buffer, offset, count, callback, state);
}
///
/// Begins an asynchronous write operation.
///
/// The buffer to write data from.
/// The byte offset in buffer from which to begin writing.
/// The maximum number of bytes to write.
///
/// An optional asynchronous callback, to be called when the write is complete.
///
///
/// A user-provided object that distinguishes this particular asynchronous
/// write request from other requests.
///
///
/// An IAsyncResult that represents the asynchronous write,
/// which could still be pending.
///
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
CheckClosed();
return stream.BeginWrite(buffer, offset, count, callback, state);
}
///
/// Indicates whether or not the underlying stream can be read from.
///
public override bool CanRead
{
get { return closed ? false : stream.CanRead; }
}
///
/// Indicates whether or not the underlying stream supports seeking.
///
public override bool CanSeek
{
get { return closed ? false : stream.CanSeek; }
}
///
/// Indicates whether or not the underlying stream can be written to.
///
public override bool CanWrite
{
get { return closed ? false : stream.CanWrite; }
}
///
/// This method is not proxied to the underlying stream; instead, the wrapper
/// is marked as unusable for other (non-close/Dispose) operations. The underlying
/// stream is flushed if the wrapper wasn't closed before this call.
///
public override void Close()
{
if (!closed)
{
stream.Flush();
}
closed = true;
}
///
/// Throws a NotSupportedException.
///
/// The Type of the object that the new ObjRef will reference.
/// n/a
public override ObjRef CreateObjRef(Type requestedType)
{
throw new NotSupportedException();
}
///
/// Waits for the pending asynchronous read to complete.
///
///
/// The reference to the pending asynchronous request to finish.
///
///
/// The number of bytes read from the stream, between zero (0)
/// and the number of bytes you requested. Streams only return
/// zero (0) at the end of the stream, otherwise, they should
/// block until at least one byte is available.
///
public override int EndRead(IAsyncResult asyncResult)
{
CheckClosed();
return stream.EndRead(asyncResult);
}
///
/// Ends an asynchronous write operation.
///
/// A reference to the outstanding asynchronous I/O request.
public override void EndWrite(IAsyncResult asyncResult)
{
CheckClosed();
stream.EndWrite(asyncResult);
}
///
/// Flushes the underlying stream.
///
public override void Flush()
{
CheckClosed();
stream.Flush();
}
///
/// Throws a NotSupportedException.
///
/// n/a
public override object InitializeLifetimeService()
{
throw new NotSupportedException();
}
///
/// Returns the length of the underlying stream.
///
public override long Length
{
get
{
CheckClosed();
return stream.Length;
}
}
///
/// Gets or sets the current position in the underlying stream.
///
public override long Position
{
get
{
CheckClosed();
return stream.Position;
}
set
{
CheckClosed();
stream.Position = value;
}
}
///
/// Reads a sequence of bytes from the underlying stream and advances the
/// position within the stream by the number of bytes read.
///
///
/// An array of bytes. When this method returns, the buffer contains
/// the specified byte array with the values between offset and
/// (offset + count- 1) replaced by the bytes read from the underlying source.
///
///
/// The zero-based byte offset in buffer at which to begin storing the data
/// read from the underlying stream.
///
///
/// The maximum number of bytes to be read from the
/// underlying stream.
///
/// The total number of bytes read into the buffer.
/// This can be less than the number of bytes requested if that many
/// bytes are not currently available, or zero (0) if the end of the
/// stream has been reached.
///
public override int Read(byte[] buffer, int offset, int count)
{
CheckClosed();
return stream.Read(buffer, offset, count);
}
///
/// Reads a byte from the stream and advances the position within the
/// stream by one byte, or returns -1 if at the end of the stream.
///
/// The unsigned byte cast to an Int32, or -1 if at the end of the stream.
public override int ReadByte()
{
CheckClosed();
return stream.ReadByte();
}
///
/// Sets the position within the current stream.
///
/// A byte offset relative to the origin parameter.
///
/// A value of type SeekOrigin indicating the reference
/// point used to obtain the new position.
///
/// The new position within the underlying stream.
public override long Seek(long offset, SeekOrigin origin)
{
CheckClosed();
return stream.Seek(offset, origin);
}
///
/// Sets the length of the underlying stream.
///
/// The desired length of the underlying stream in bytes.
public override void SetLength(long value)
{
CheckClosed();
stream.SetLength(value);
}
///
/// Writes a sequence of bytes to the underlying stream and advances
/// the current position within the stream by the number of bytes written.
///
///
/// An array of bytes. This method copies count bytes
/// from buffer to the underlying stream.
///
///
/// The zero-based byte offset in buffer at
/// which to begin copying bytes to the underlying stream.
///
/// The number of bytes to be written to the underlying stream.
public override void Write(byte[] buffer, int offset, int count)
{
CheckClosed();
stream.Write(buffer, offset, count);
}
///
/// Writes a byte to the current position in the stream and
/// advances the position within the stream by one byte.
///
/// The byte to write to the stream.
public override void WriteByte(byte value)
{
CheckClosed();
stream.WriteByte(value);
}
#endregion
}
}