Files
OpenRA/OpenRA.Game/Primitives/SegmentStream.cs
RoosterDragon 210c7e312b Don't keep mix files in memory.
Added SegmentStream class to assist in maintaining views into portions of the FileStream of the overall mix file to avoid having to copy sections into in-memory buffers.
2015-10-13 19:23:56 +01:00

103 lines
3.2 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.ComponentModel;
using System.IO;
namespace OpenRA.Primitives
{
public class SegmentStream : Stream
{
public readonly Stream BaseStream;
public readonly long BaseOffset;
public readonly long BaseCount;
public SegmentStream(Stream stream, long offset, long count)
{
if (stream == null)
throw new ArgumentNullException("stream");
if (!stream.CanSeek)
throw new ArgumentException("stream must be seekable.", "stream");
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", "offset must be non-negative.");
if (count < 0)
throw new ArgumentOutOfRangeException("count", "count must be non-negative.");
BaseStream = stream;
BaseOffset = offset;
BaseCount = count;
stream.Seek(BaseOffset, SeekOrigin.Begin);
}
public override bool CanSeek { get { return true; } }
public override bool CanRead { get { return BaseStream.CanRead; } }
public override bool CanWrite { get { return BaseStream.CanWrite; } }
public override long Length { get { return BaseCount; } }
public override long Position
{
get { return BaseStream.Position - BaseOffset; }
set { BaseStream.Position = BaseOffset + value; }
}
public override int Read(byte[] buffer, int offset, int count) { return BaseStream.Read(buffer, offset, count); }
public override void Write(byte[] buffer, int offset, int count) { BaseStream.Write(buffer, offset, count); }
public override void Flush() { BaseStream.Flush(); }
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
default: throw new InvalidEnumArgumentException("origin", (int)origin, typeof(SeekOrigin));
case SeekOrigin.Begin:
return BaseStream.Seek(BaseOffset + offset, SeekOrigin.Begin) - offset;
case SeekOrigin.Current:
return BaseStream.Seek(offset, SeekOrigin.Current) - offset;
case SeekOrigin.End:
return BaseStream.Seek(offset, SeekOrigin.End) - offset;
}
}
public override void SetLength(long value) { throw new NotSupportedException(); }
public override bool CanTimeout { get { return BaseStream.CanTimeout; } }
public override int ReadTimeout
{
get { return BaseStream.ReadTimeout; }
set { BaseStream.ReadTimeout = value; }
}
public override int WriteTimeout
{
get { return BaseStream.WriteTimeout; }
set { BaseStream.WriteTimeout = value; }
}
protected override void Dispose(bool disposing)
{
if (disposing)
BaseStream.Dispose();
base.Dispose(disposing);
}
public static long GetOverallNestedOffset(Stream stream, out Stream overallBaseStream)
{
var offset = 0L;
overallBaseStream = stream;
var segmentStream = stream as SegmentStream;
if (segmentStream != null)
offset += segmentStream.BaseOffset + GetOverallNestedOffset(segmentStream.BaseStream, out overallBaseStream);
return offset;
}
}
}