Skip to content

Instantly share code, notes, and snippets.

@RyuaNerin
Created September 30, 2015 16:21
Show Gist options
  • Save RyuaNerin/a4d52e240a4b71d763f9 to your computer and use it in GitHub Desktop.
Save RyuaNerin/a4d52e240a4b71d763f9 to your computer and use it in GitHub Desktop.
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