using System; using System.IO; namespace SonicAudioLib.IO { /// /// Represents a based substream for viewing a portion of a Stream. /// public class Substream : Stream { private Stream baseStream; private long streamPosition; private long streamLength; /// /// Determines whether the base Stream supports reading. /// public override bool CanRead { get { return baseStream.CanRead; } } /// /// Determines whether the base Stream supports seeking. /// public override bool CanSeek { get { return baseStream.CanSeek; } } /// /// Always returns false. /// public override bool CanWrite { get { return false; } } /// /// Gets the length of the substream. /// public override long Length { get { return streamLength; } } /// /// Gets or sets the position of the substream. /// public override long Position { get { return baseStream.Position - streamPosition; } set { baseStream.Position = value + streamPosition; } } /// /// Gets or sets the position of the base Stream. /// public long AbsolutePosition { get { return baseStream.Position; } set { baseStream.Position = value; } } /// /// Closes the substream. /// public override void Close() { base.Close(); } /// /// Does nothing. /// public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { if (baseStream.Position >= streamPosition + streamLength) { count = 0; } else if (baseStream.Position + count > streamPosition + streamLength) { count = (int)(streamPosition + streamLength - baseStream.Position); } return baseStream.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { if (origin == SeekOrigin.Begin) { offset += streamPosition; } else if (origin == SeekOrigin.End) { offset = streamPosition + streamLength - offset; origin = SeekOrigin.Begin; } return baseStream.Seek(offset, origin); } /// /// Seeks to the start of the substream. /// public void SeekToStart() { baseStream.Position = streamPosition; } /// /// Throws . /// public override void SetLength(long value) { throw new NotSupportedException(); } /// /// Throws . /// public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } /// /// Throws . /// public override void WriteByte(byte value) { throw new NotSupportedException(); } /// /// Gets an array of the data that the substream covers. /// public byte[] ToArray() { using (MemoryStream memoryStream = new MemoryStream()) { CopyTo(memoryStream); return memoryStream.ToArray(); } } /// /// Creates a substream by the specified base Stream at the specified offset. /// public Substream(Stream baseStream, long streamPosition) : this(baseStream, streamPosition, baseStream.Length - streamPosition) { } /// /// Creates a substream by the specified base Stream at the specified offset and with the specified length. /// public Substream(Stream baseStream, long streamPosition, long streamLength) { this.baseStream = baseStream; this.streamPosition = streamPosition; this.streamLength = streamLength; SeekToStart(); } } }