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;
int outPos = 0;
int remaining = destination.Length;
int sourceIndex = FindSource(inPos);
while (remaining > 0)
{
ConcatSource entry = FindSource(inPos);
long sourcePos = inPos - entry.StartOffset;
ConcatSource entry = Sources[sourceIndex];
long entryPos = inPos - entry.StartOffset;
long entryRemain = entry.StartOffset + entry.Size - inPos;
int bytesToRead = (int)Math.Min(entry.EndOffset - inPos, remaining);
entry.Storage.Read(destination.Slice(outPos, bytesToRead), sourcePos);
int bytesToRead = (int)Math.Min(entryRemain, remaining);
entry.Storage.Read(destination.Slice(outPos, bytesToRead), entryPos);
outPos += bytesToRead;
inPos += bytesToRead;
remaining -= bytesToRead;
sourceIndex++;
}
}
@ -49,18 +52,21 @@ namespace LibHac.IO
long inPos = offset;
int outPos = 0;
int remaining = source.Length;
int sourceIndex = FindSource(inPos);
while (remaining > 0)
{
ConcatSource storage = FindSource(inPos);
long sourcePos = inPos - storage.StartOffset;
ConcatSource entry = Sources[sourceIndex];
long entryPos = inPos - entry.StartOffset;
long entryRemain = entry.StartOffset + entry.Size - inPos;
int bytesToWrite = (int)Math.Min(storage.EndOffset - inPos, remaining);
storage.Storage.Write(source.Slice(outPos, bytesToWrite), sourcePos);
int bytesToWrite = (int)Math.Min(entryRemain, remaining);
entry.Storage.Write(source.Slice(outPos, bytesToWrite), entryPos);
outPos += bytesToWrite;
inPos += 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
{
public IStorage Storage { get; }
public long StartOffset { get; }
public long EndOffset { get; }
public long Size { get; }
public ConcatSource(IStorage storage, long startOffset, long length)
{
Storage = storage;
StartOffset = startOffset;
EndOffset = startOffset + length;
Size = length;
}
}
}