Created
September 30, 2015 16:21
-
-
Save RyuaNerin/a4d52e240a4b71d763f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
namespace RyuaNerin | |
{ | |
internal class RangeStream : Stream | |
{ | |
private Stream m_baseStream; | |
private long m_currentPos; | |
private int m_offset; | |
private int m_streamEnd; | |
private int m_length; | |
private bool m_leaveOpen; | |
public ExRangeStream(Stream baseStream, int offset, int length, bool leaveOpen) | |
{ | |
this.m_baseStream = baseStream; | |
this.m_offset = offset; | |
this.m_length = length; | |
this.m_streamEnd = offset + length; | |
this.m_leaveOpen = leaveOpen; | |
this.m_currentPos = 0; | |
if (this.m_baseStream.Length < this.m_streamEnd) throw new IOException(); | |
if (!this.m_baseStream.CanSeek || !this.m_baseStream.CanRead) throw new NotSupportedException(); | |
} | |
public override bool CanRead { get { return this.m_baseStream.CanRead; } } | |
public override bool CanSeek { get { return true; } } | |
public override bool CanTimeout { get { return this.m_baseStream.CanTimeout; } } | |
public override bool CanWrite { get { return false; } } | |
public override long Length { get { return this.m_length; } } | |
public override long Position | |
{ | |
get { return this.m_currentPos; } | |
set | |
{ | |
this.m_baseStream.Position = this.m_offset + value; | |
this.m_currentPos = (int)value; | |
} | |
} | |
public override int ReadTimeout | |
{ | |
get { return this.m_baseStream.ReadTimeout; } | |
set { this.m_baseStream.ReadTimeout = value; } | |
} | |
public override int WriteTimeout | |
{ | |
get { return this.m_baseStream.WriteTimeout; } | |
set { this.m_baseStream.WriteTimeout = value; } | |
} | |
public override void Flush() | |
{ | |
throw new NotSupportedException(); | |
} | |
public override void Close() | |
{ | |
if (!this.m_leaveOpen) | |
this.m_baseStream.Close(); | |
base.Close(); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (this.m_baseStream != null) | |
{ | |
if (!this.m_leaveOpen) this.m_baseStream.Dispose(); | |
this.m_baseStream = null; | |
} | |
base.Dispose(disposing); | |
} | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
if (this.m_currentPos + count >= this.m_length) | |
count = this.m_length - (int)this.m_currentPos; | |
if (count == 0) return 0; | |
this.m_baseStream.Position = this.m_offset + this.m_currentPos; | |
var read = this.m_baseStream.Read(buffer, offset, count); | |
this.m_currentPos += read; | |
return read; | |
} | |
public override int ReadByte() | |
{ | |
if (this.Position == this.Length) | |
throw new IndexOutOfRangeException(); | |
this.m_baseStream.Position = this.m_offset + this.m_currentPos; | |
var r = this.m_baseStream.ReadByte(); | |
++this.m_currentPos; | |
return r; | |
} | |
public override long Seek(long offset, SeekOrigin origin) | |
{ | |
if (origin == SeekOrigin.Begin) | |
{ | |
if (this.m_offset + offset < this.m_streamEnd) throw new IndexOutOfRangeException(); | |
this.m_currentPos = offset; | |
return this.m_baseStream.Seek(this.m_offset + offset, origin); | |
} | |
else if (origin == SeekOrigin.Current) | |
{ | |
if (this.Position + offset > this.m_streamEnd) throw new IndexOutOfRangeException(); | |
this.m_currentPos += offset; | |
return this.m_baseStream.Seek(offset, origin); | |
} | |
else if (origin == SeekOrigin.End) | |
{ | |
if (this.m_streamEnd - offset < this.m_offset) throw new IndexOutOfRangeException(); | |
this.m_currentPos = this.m_length - offset - 1; | |
return this.m_baseStream.Seek(this.m_streamEnd - offset, origin); | |
} | |
return -1; | |
} | |
public override void SetLength(long value) | |
{ | |
throw new NotSupportedException(); | |
} | |
public override void Write(byte[] buffer, int offset, int count) | |
{ | |
throw new NotSupportedException(); | |
} | |
public override void WriteByte(byte value) | |
{ | |
throw new NotSupportedException(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment