GDROMExplorer/ImageReader/Stream/DiscSectorStream.cs
2021-07-26 13:04:16 -07:00

211 lines
8.5 KiB
C#

// Decompiled with JetBrains decompiler
// Type: ImageReader.Stream.DiscSectorStream
// Assembly: ImageReader, Version=1.5.2.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08
// MVID: E0717604-B50B-4CB4-B85C-C17F43D5C04B
// Assembly location: ImageReader.dll
using ImageReader.DiscSectors;
using System;
using System.IO;
namespace ImageReader.Stream
{
public class DiscSectorStream : System.IO.Stream
{
private System.IO.Stream sourceStream;
private IDiscSector sector;
private long absStartAddress;
private long absEndAddress;
private bool disposed;
private bool disposeSourceStream;
public DiscSectorStream(
System.IO.Stream source,
IDiscSector sector,
uint extent,
uint size,
bool autoReleaseSource)
{
this.disposed = false;
if (size > (uint) int.MaxValue)
throw new ArgumentException(string.Format("invalid size: files larger than {0} in size are not supported", (object) int.MaxValue), nameof (size));
if (size > uint.MaxValue)
throw new ArgumentException(string.Format("invalid size: a file on an ISO 9660 formatted disc cannot be larger than {0} in size", (object) uint.MaxValue), nameof (size));
if (!source.CanSeek)
throw new ArgumentException(string.Format("invalid base stream: only seekable streams are supported"), "baseStream");
this.sector = sector;
this.sourceStream = source;
this.absStartAddress = (long) extent * (long) sector.Size;
this.absEndAddress = this.absStartAddress + this.LogicalToPhysical((long) size);
this.disposeSourceStream = autoReleaseSource;
this.Seek(0L, SeekOrigin.Begin);
}
public DiscSectorStream(string isoFile, IDiscSector sector, uint extent, uint size)
: this((System.IO.Stream) new FileStream(isoFile, FileMode.Open, FileAccess.Read, FileShare.Read), sector, extent, size, true)
{
}
public DiscSectorStream(System.IO.Stream source, IDiscSector sector)
: this(source, sector, 0U, 0U, true)
=> this.absEndAddress = this.absStartAddress + source.Length;
public override bool CanRead => !this.disposed && this.sourceStream.CanRead;
public override bool CanTimeout => this.disposed || this.sourceStream.CanTimeout;
public override bool CanSeek => !this.disposed && this.sourceStream.CanSeek;
public override bool CanWrite => !this.disposed && this.sourceStream.CanWrite;
public override long Length => this.PhysicalToLogical(this.absEndAddress - this.absStartAddress);
public override long Position
{
get => this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress);
set => this.Seek(value, SeekOrigin.Begin);
}
public override int Read(byte[] buffer, int offset, int count)
{
long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress);
long num1 = Math.Min((long) count, this.Length - logical);
long sectors = num1 / (long) this.sector.DataLength;
long num2 = num1 % (long) this.sector.DataLength;
int num3 = 0;
if ((long) (buffer.Length - offset) < sectors * (long) this.sector.DataLength + num2)
throw new ArgumentOutOfRangeException("buffer is too small");
if (sectors > 0L)
num3 += this.ReadSector(buffer, offset, sectors);
if (num2 > 0L)
{
if (this.sourceStream.Position % (long) this.sector.Size == 0L)
this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current);
num3 += this.sourceStream.Read(buffer, Convert.ToInt32(sectors * (long) this.sector.DataLength), (int) num2);
}
return num3;
}
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer.Length - offset < count)
throw new ArgumentOutOfRangeException("buffer is too small");
long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress);
long num1 = Math.Min((long) count, this.Length - logical);
long sectors = num1 / (long) this.sector.DataLength;
long num2 = num1 % (long) this.sector.DataLength;
long num3 = 0;
if (sectors > 0L)
num3 += (long) this.WriteSector(buffer, offset, sectors);
if (num2 <= 0L)
return;
if (sectors > 0L || this.sourceStream.Position == this.absStartAddress)
this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current);
this.sourceStream.Write(buffer, Convert.ToInt32(sectors * (long) this.sector.DataLength), (int) num2);
long num4 = num3 + num2;
}
public override long Seek(long offset, SeekOrigin origin)
{
long offset1;
switch (origin)
{
case SeekOrigin.Begin:
if (offset < 0L || offset > this.Length)
throw new ArgumentException(string.Format("must be in range of (0, {0}) when seeking from {1}", (object) this.Length, (object) SeekOrigin.Begin), nameof (offset));
offset1 = this.absStartAddress + this.LogicalToPhysical(offset);
break;
case SeekOrigin.Current:
long logical = this.PhysicalToLogical(this.sourceStream.Position - this.absStartAddress);
if ((offset > 0L || logical + offset < 0L) && (offset < 0L || logical + offset > this.Length))
throw new ArgumentException(string.Format("must be in range of (0, {0}) or (-{0}, 0) when seeking from {1}", (object) this.Length, (object) SeekOrigin.Current), nameof (offset));
offset1 = this.LogicalToPhysical(logical + offset) - (this.sourceStream.Position - this.absStartAddress);
break;
case SeekOrigin.End:
if (offset > 0L || this.Length + offset < 0L)
throw new ArgumentException(string.Format("must be in range of (-{0}, 0) when seeking from {1}", (object) this.Length, (object) SeekOrigin.End), nameof (offset));
offset1 = this.absStartAddress + this.LogicalToPhysical(this.Length + offset);
origin = SeekOrigin.Begin;
break;
default:
throw new ArgumentException();
}
return this.PhysicalToLogical(this.sourceStream.Seek(offset1, origin) - this.absStartAddress);
}
public override void Close()
{
if (this.sourceStream == null || !this.disposeSourceStream)
return;
this.sourceStream.Close();
}
public override void SetLength(long value) => throw new NotSupportedException();
public override void WriteByte(byte value) => throw new NotSupportedException();
public override void Flush() => throw new NotSupportedException();
private long LogicalToPhysical(long logicalAddress)
{
long num1 = logicalAddress / (long) this.sector.DataLength;
long num2 = logicalAddress % (long) this.sector.DataLength;
if (num2 != 0L)
num2 += (long) this.sector.DataOffset;
return num1 * (long) this.sector.Size + num2;
}
private long PhysicalToLogical(long physicalAddress)
{
long num1 = physicalAddress % (long) this.sector.Size;
long num2 = physicalAddress / (long) this.sector.Size;
if (num1 != 0L)
{
string.Format("the specified absolute address {0} is out of the stream's logical range", (object) physicalAddress);
num1 -= (long) this.sector.DataOffset;
}
return num2 * (long) this.sector.DataLength + num1;
}
private int ReadSector(byte[] buffer, int offset, long sectors)
{
int num = 0;
byte[] buffer1 = new byte[this.sector.Size];
for (int index = 0; (long) index < sectors; ++index)
{
this.sourceStream.Read(buffer1, 0, buffer1.Length);
Buffer.BlockCopy((Array) buffer1, this.sector.DataOffset, (Array) buffer, offset + index * this.sector.DataLength, this.sector.DataLength);
num += this.sector.DataLength;
}
return num;
}
private int WriteSector(byte[] buffer, int offset, long sectors)
{
int num = 0;
for (int index = 0; (long) index < sectors; ++index)
{
this.sourceStream.Seek((long) this.sector.DataOffset, SeekOrigin.Current);
this.sourceStream.Write(buffer, offset + index * this.sector.DataLength, this.sector.DataLength);
this.sourceStream.Seek((long) (this.sector.Size - this.sector.DataOffset), SeekOrigin.Current);
num += this.sector.DataLength;
}
return num;
}
public new virtual void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize((object) this);
}
protected new virtual void Dispose(bool disposing)
{
if (this.disposed)
return;
if (disposing)
this.Close();
this.disposed = true;
}
}
}