Skip to content

Commit

Permalink
Spanify indexed reader classes
Browse files Browse the repository at this point in the history
Allows avoidance of temporary byte arrays, reduces the number of virtual calls to `GetByteInternal`, and uses conversion methods optimised by the framework (e.g. `BinaryPrimitives`).
  • Loading branch information
drewnoakes committed Jan 27, 2024
1 parent 8a71b59 commit ee67dfb
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 206 deletions.
8 changes: 6 additions & 2 deletions MetadataExtractor.Tests/IO/IndexedReaderTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ public void GetFloat32()

var reader = CreateReader(0x7f, 0xc0, 0x00, 0x00);

Assert.True(float.IsNaN(reader.GetFloat32(0)));
float f = reader.GetFloat32(0);

Assert.True(float.IsNaN(f), $"Expected NaN, got {f}.");
}

[Fact]
Expand All @@ -199,7 +201,9 @@ public void GetFloat64()

var reader = CreateReader(0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);

Assert.True(double.IsNaN(reader.GetDouble64(0)));
double d = reader.GetDouble64(0);

Assert.True(double.IsNaN(d), $"Expected NaN, got {d}.");
}

[Fact]
Expand Down
17 changes: 5 additions & 12 deletions MetadataExtractor/IO/ByteArrayReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ public ByteArrayReader(byte[] buffer, int baseOffset = 0, bool isMotorolaByteOrd

public override long Length => _buffer.Length - _baseOffset;

protected override byte GetByteInternal(int index)
public override void GetBytes(int index, Span<byte> bytes)
{
return _buffer[index + _baseOffset];
ValidateIndex(index, bytes.Length);

_buffer.AsSpan().Slice(index + _baseOffset, bytes.Length).CopyTo(bytes);
}

protected override void ValidateIndex(int index, int bytesRequested)
Expand All @@ -44,21 +46,12 @@ protected override void ValidateIndex(int index, int bytesRequested)
throw new BufferBoundsException(ToUnshiftedOffset(index), bytesRequested, _buffer.Length);
}

protected override bool IsValidIndex(int index, int bytesRequested)
private bool IsValidIndex(int index, int bytesRequested)
{
return
bytesRequested >= 0 &&
index >= 0 &&
index + (long)bytesRequested - 1L < Length;
}

public override byte[] GetBytes(int index, int count)
{
ValidateIndex(index, count);

var bytes = new byte[count];
Array.Copy(_buffer, index + _baseOffset, bytes, 0, count);
return bytes;
}
}
}
25 changes: 6 additions & 19 deletions MetadataExtractor/IO/IndexedCapturingReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected override void ValidateIndex(int index, int bytesRequested)
}
}

protected override bool IsValidIndex(int index, int bytesRequested)
private bool IsValidIndex(int index, int bytesRequested)
{
if (index < 0 || bytesRequested < 0)
return false;
Expand Down Expand Up @@ -143,32 +143,23 @@ private void GetPosition(int index, out int chunkIndex, out int innerIndex)
#endif
}

protected override byte GetByteInternal(int index)
public override void GetBytes(int index, Span<byte> bytes)
{
GetPosition(index, out int chunkIndex, out int innerIndex);
var chunk = _chunks[chunkIndex];
return chunk[innerIndex];
}

public override byte[] GetBytes(int index, int count)
{
ValidateIndex(index, count);
ValidateIndex(index, bytes.Length);

var bytes = new byte[count];
var remaining = count;
var remaining = bytes.Length;
var fromIndex = index;
var toIndex = 0;
while (remaining != 0)
{
GetPosition(fromIndex, out int fromChunkIndex, out int fromInnerIndex);
var length = Math.Min(remaining, _chunkLength - fromInnerIndex);
var chunk = _chunks[fromChunkIndex];
Array.Copy(chunk, fromInnerIndex, bytes, toIndex, length);
chunk.AsSpan().Slice(fromInnerIndex, length).CopyTo(bytes.Slice(toIndex, length));
remaining -= length;
fromIndex += length;
toIndex += length;
}
return bytes;
}

public override IndexedReader WithByteOrder(bool isMotorolaByteOrder) => isMotorolaByteOrder == IsMotorolaByteOrder ? this : new ShiftedIndexedCapturingReader(this, 0, isMotorolaByteOrder);
Expand Down Expand Up @@ -196,14 +187,10 @@ public ShiftedIndexedCapturingReader(IndexedCapturingReader baseReader, int base

public override int ToUnshiftedOffset(int localOffset) => localOffset + _baseOffset;

protected override byte GetByteInternal(int index) => _baseReader.GetByteInternal(_baseOffset + index);

public override byte[] GetBytes(int index, int count) => _baseReader.GetBytes(_baseOffset + index, count);
public override void GetBytes(int index, Span<byte> bytes) => _baseReader.GetBytes(_baseOffset + index, bytes);

protected override void ValidateIndex(int index, int bytesRequested) => _baseReader.ValidateIndex(index + _baseOffset, bytesRequested);

protected override bool IsValidIndex(int index, int bytesRequested) => _baseReader.IsValidIndex(index + _baseOffset, bytesRequested);

public override long Length => _baseReader.Length - _baseOffset;
}
}
Expand Down
Loading

0 comments on commit ee67dfb

Please sign in to comment.