Do a binary search in ConcatenationStorage when finding a source

This commit is contained in:
Alex Barney 2019-02-25 12:36:54 -06:00
parent 53851ab897
commit 1c918f705b

View file

@ -29,18 +29,21 @@ namespace LibHac.IO
long inPos = offset; long inPos = offset;
int outPos = 0; int outPos = 0;
int remaining = destination.Length; int remaining = destination.Length;
int sourceIndex = FindSource(inPos);
while (remaining > 0) while (remaining > 0)
{ {
ConcatSource entry = FindSource(inPos); ConcatSource entry = Sources[sourceIndex];
long sourcePos = inPos - entry.StartOffset; long entryPos = inPos - entry.StartOffset;
long entryRemain = entry.StartOffset + entry.Size - inPos;
int bytesToRead = (int)Math.Min(entry.EndOffset - inPos, remaining); int bytesToRead = (int)Math.Min(entryRemain, remaining);
entry.Storage.Read(destination.Slice(outPos, bytesToRead), sourcePos); entry.Storage.Read(destination.Slice(outPos, bytesToRead), entryPos);
outPos += bytesToRead; outPos += bytesToRead;
inPos += bytesToRead; inPos += bytesToRead;
remaining -= bytesToRead; remaining -= bytesToRead;
sourceIndex++;
} }
} }
@ -49,18 +52,21 @@ namespace LibHac.IO
long inPos = offset; long inPos = offset;
int outPos = 0; int outPos = 0;
int remaining = source.Length; int remaining = source.Length;
int sourceIndex = FindSource(inPos);
while (remaining > 0) while (remaining > 0)
{ {
ConcatSource storage = FindSource(inPos); ConcatSource entry = Sources[sourceIndex];
long sourcePos = inPos - storage.StartOffset; long entryPos = inPos - entry.StartOffset;
long entryRemain = entry.StartOffset + entry.Size - inPos;
int bytesToWrite = (int)Math.Min(storage.EndOffset - inPos, remaining); int bytesToWrite = (int)Math.Min(entryRemain, remaining);
storage.Storage.Write(source.Slice(outPos, bytesToWrite), sourcePos); entry.Storage.Write(source.Slice(outPos, bytesToWrite), entryPos);
outPos += bytesToWrite; outPos += bytesToWrite;
inPos += bytesToWrite; inPos += bytesToWrite;
remaining -= bytesToWrite; remaining -= bytesToWrite;
sourceIndex++;
} }
} }
@ -72,27 +78,46 @@ namespace LibHac.IO
} }
} }
private ConcatSource FindSource(long offset) private int FindSource(long offset)
{ {
foreach (ConcatSource info in Sources) if (offset < 0 || offset >= Length)
throw new ArgumentOutOfRangeException(nameof(offset), offset, "The Storage does not contain this offset.");
int lo = 0;
int hi = Sources.Length - 1;
while (lo <= hi)
{ {
if (info.EndOffset > offset) return info; int mid = lo + ((hi - lo) >> 1);
long val = Sources[mid].StartOffset;
if (val == offset) return mid;
if (val < offset)
{
lo = mid + 1;
}
else
{
hi = mid - 1;
}
} }
throw new ArgumentOutOfRangeException(nameof(offset), offset, "The Storage does not contain this offset."); return lo - 1;
} }
private class ConcatSource private class ConcatSource
{ {
public IStorage Storage { get; } public IStorage Storage { get; }
public long StartOffset { get; } public long StartOffset { get; }
public long EndOffset { get; } public long Size { get; }
public ConcatSource(IStorage storage, long startOffset, long length) public ConcatSource(IStorage storage, long startOffset, long length)
{ {
Storage = storage; Storage = storage;
StartOffset = startOffset; StartOffset = startOffset;
EndOffset = startOffset + length; Size = length;
} }
} }
} }