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.
This commit is contained in:
@@ -14,6 +14,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.FileSystem
|
||||
{
|
||||
@@ -179,9 +180,10 @@ namespace OpenRA.FileSystem
|
||||
if (!index.TryGetValue(hash, out e))
|
||||
return null;
|
||||
|
||||
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
||||
var data = s.ReadBytes((int)e.Length);
|
||||
return new MemoryStream(data);
|
||||
Stream parentStream;
|
||||
var offset = dataStart + e.Offset + SegmentStream.GetOverallNestedOffset(s, out parentStream);
|
||||
var path = ((FileStream)parentStream).Name;
|
||||
return new SegmentStream(File.OpenRead(path), offset, e.Length);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
|
||||
@@ -150,6 +150,7 @@
|
||||
<Compile Include="Orders\UnitOrderGenerator.cs" />
|
||||
<Compile Include="Player.cs" />
|
||||
<Compile Include="Primitives\MergedStream.cs" />
|
||||
<Compile Include="Primitives\SegmentStream.cs" />
|
||||
<Compile Include="Primitives\SpatiallyPartitioned.cs" />
|
||||
<Compile Include="Primitives\ConcurrentCache.cs" />
|
||||
<Compile Include="SelectableExts.cs" />
|
||||
|
||||
102
OpenRA.Game/Primitives/SegmentStream.cs
Normal file
102
OpenRA.Game/Primitives/SegmentStream.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user