Spanify IInputBytes

This commit is contained in:
Jason Nelson 2024-04-01 21:38:42 -07:00 committed by BobLd
parent 775d1343ae
commit e01bf5e849
7 changed files with 71 additions and 77 deletions

View File

@ -47,8 +47,7 @@
/// Fill the buffer with bytes starting from the current position. /// Fill the buffer with bytes starting from the current position.
/// </summary> /// </summary>
/// <param name="buffer">A buffer with a length corresponding to the number of bytes to read.</param> /// <param name="buffer">A buffer with a length corresponding to the number of bytes to read.</param>
/// <param name="length">Optional override for the number of bytes to read.</param>
/// <returns>The number of bytes successfully read.</returns> /// <returns>The number of bytes successfully read.</returns>
int Read(byte[] buffer, int? length = null); int Read(Span<byte> buffer);
} }
} }

View File

@ -7,7 +7,7 @@
/// <summary> /// <summary>
/// Input bytes from a byte array. /// Input bytes from a byte array.
/// </summary> /// </summary>
public class MemoryInputBytes : IInputBytes public sealed class MemoryInputBytes : IInputBytes
{ {
private readonly int upperBound; private readonly int upperBound;
private readonly ReadOnlyMemory<byte> memory; private readonly ReadOnlyMemory<byte> memory;
@ -73,31 +73,15 @@
} }
/// <inheritdoc /> /// <inheritdoc />
public int Read(byte[] buffer, int? length = null) public int Read(Span<byte> buffer)
{ {
var bytesToRead = buffer.Length; if (buffer.IsEmpty)
if (length.HasValue)
{
if (length.Value < 0)
{
throw new ArgumentOutOfRangeException($"Cannot use a negative length: {length.Value}.");
}
if (length.Value > bytesToRead)
{
throw new ArgumentOutOfRangeException($"Cannot read more bytes {length.Value} than there is space in the buffer {buffer.Length}.");
}
bytesToRead = length.Value;
}
if (bytesToRead == 0)
{ {
return 0; return 0;
} }
var viableLength = (memory.Length - currentOffset - 1); var viableLength = (memory.Length - currentOffset - 1);
var readLength = viableLength < bytesToRead ? viableLength : bytesToRead; var readLength = viableLength < buffer.Length ? viableLength : buffer.Length;
var startFrom = currentOffset + 1; var startFrom = currentOffset + 1;
memory.Span.Slice(startFrom, readLength).CopyTo(buffer); memory.Span.Slice(startFrom, readLength).CopyTo(buffer);

View File

@ -6,19 +6,37 @@ using System.Buffers;
internal static class StreamExtensions internal static class StreamExtensions
{ {
public static void Write(this Stream stream, ReadOnlySpan<byte> data) public static void Write(this Stream stream, ReadOnlySpan<byte> buffer)
{ {
var buffer = ArrayPool<byte>.Shared.Rent(data.Length); var tempBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
data.CopyTo(buffer); buffer.CopyTo(tempBuffer);
try try
{ {
stream.Write(buffer, 0, data.Length); stream.Write(tempBuffer, 0, buffer.Length);
} }
finally finally
{ {
ArrayPool<byte>.Shared.Return(buffer); ArrayPool<byte>.Shared.Return(tempBuffer);
}
}
public static int Read(this Stream stream, Span<byte> buffer)
{
var tempBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
try
{
int read = stream.Read(tempBuffer, 0, buffer.Length);
tempBuffer.AsSpan(0, read).CopyTo(buffer);
return read;
}
finally
{
ArrayPool<byte>.Shared.Return(tempBuffer);
} }
} }
} }

View File

@ -7,7 +7,7 @@
/// <summary> /// <summary>
/// Input bytes from a stream. /// Input bytes from a stream.
/// </summary> /// </summary>
public class StreamInputBytes : IInputBytes public sealed class StreamInputBytes : IInputBytes
{ {
private readonly Stream stream; private readonly Stream stream;
private readonly bool shouldDispose; private readonly bool shouldDispose;
@ -106,30 +106,15 @@
} }
/// <inheritdoc /> /// <inheritdoc />
public int Read(byte[] buffer, int? length = null) public int Read(Span<byte> buffer)
{ {
var bytesToRead = buffer.Length; if (buffer.IsEmpty)
if (length.HasValue)
{
if (length.Value < 0)
{
throw new ArgumentOutOfRangeException($"Cannot use a negative length: {length.Value}.");
}
if (length.Value > bytesToRead)
{
throw new ArgumentOutOfRangeException($"Cannot read more bytes {length.Value} than there is space in the buffer {buffer.Length}.");
}
bytesToRead = length.Value;
}
if (bytesToRead == 0)
{ {
return 0; return 0;
} }
var read = stream.Read(buffer, 0, bytesToRead); int read = stream.Read(buffer);
if (read > 0) if (read > 0)
{ {
CurrentByte = buffer[read - 1]; CurrentByte = buffer[read - 1];

View File

@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.TrueType namespace UglyToad.PdfPig.Fonts.TrueType
{ {
using System; using System;
using System.Buffers.Binary;
using System.Text; using System.Text;
using Core; using Core;
@ -9,7 +10,6 @@
/// </summary> /// </summary>
public class TrueTypeDataBytes public class TrueTypeDataBytes
{ {
private readonly byte[] internalBuffer = new byte[16];
private readonly IInputBytes inputBytes; private readonly IInputBytes inputBytes;
/// <summary> /// <summary>
@ -50,9 +50,11 @@
/// </summary> /// </summary>
public short ReadSignedShort() public short ReadSignedShort()
{ {
ReadBuffered(internalBuffer, 2); Span<byte> buffer = stackalloc byte[2];
return unchecked((short)((internalBuffer[0] << 8) + (internalBuffer[1] << 0))); ReadBuffered(buffer);
return unchecked((short)((buffer[0] << 8) + (buffer[1] << 0)));
} }
/// <summary> /// <summary>
@ -60,9 +62,11 @@
/// </summary> /// </summary>
public ushort ReadUnsignedShort() public ushort ReadUnsignedShort()
{ {
ReadBuffered(internalBuffer, 2); Span<byte> buffer = stackalloc byte[2];
return (ushort)((internalBuffer[0] << 8) + (internalBuffer[1] << 0)); ReadBuffered(buffer);
return (ushort)((buffer[0] << 8) + (buffer[1] << 0));
} }
/// <summary> /// <summary>
@ -70,9 +74,11 @@
/// </summary> /// </summary>
public byte ReadByte() public byte ReadByte()
{ {
ReadBuffered(internalBuffer, 1); Span<byte> buffer = stackalloc byte[1];
return internalBuffer[0]; ReadBuffered(buffer);
return buffer[0];
} }
/// <summary> /// <summary>
@ -99,8 +105,11 @@
return false; return false;
} }
byte[] data = new byte[bytesToRead]; Span<byte> data = bytesToRead <= 64
if (ReadBuffered(data, bytesToRead)) ? stackalloc byte[bytesToRead]
: new byte[bytesToRead];
if (ReadBuffered(data))
{ {
result = encoding.GetString(data); result = encoding.GetString(data);
return true; return true;
@ -114,9 +123,11 @@
/// </summary> /// </summary>
public uint ReadUnsignedInt() public uint ReadUnsignedInt()
{ {
ReadBuffered(internalBuffer, 4); Span<byte> buffer = stackalloc byte[4];
return (uint)(((long)internalBuffer[0] << 24) + ((long)internalBuffer[1] << 16) + (internalBuffer[2] << 8) + (internalBuffer[3] << 0)); ReadBuffered(buffer);
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
} }
/// <summary> /// <summary>
@ -124,9 +135,11 @@
/// </summary> /// </summary>
public int ReadSignedInt() public int ReadSignedInt()
{ {
ReadBuffered(internalBuffer, 4); Span<byte> buffer = stackalloc byte[4];
return (internalBuffer[0] << 24) + (internalBuffer[1] << 16) + (internalBuffer[2] << 8) + (internalBuffer[3] << 0); ReadBuffered(buffer);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
} }
/// <summary> /// <summary>
@ -175,9 +188,11 @@
/// </summary> /// </summary>
public int ReadSignedByte() public int ReadSignedByte()
{ {
ReadBuffered(internalBuffer, 1); Span<byte> buffer = stackalloc byte[1];
var signedByte = internalBuffer[0]; ReadBuffered(buffer);
var signedByte = buffer[0];
return signedByte < 127 ? signedByte : signedByte - 256; return signedByte < 127 ? signedByte : signedByte - 256;
} }
@ -204,7 +219,7 @@
{ {
var result = new byte[length]; var result = new byte[length];
ReadBuffered(result, length); ReadBuffered(result);
return result; return result;
} }
@ -244,15 +259,9 @@
return $"@: {Position} of {inputBytes.Length} bytes."; return $"@: {Position} of {inputBytes.Length} bytes.";
} }
private bool ReadBuffered(byte[] buffer, int length) private bool ReadBuffered(Span<byte> buffer)
{ {
var read = inputBytes.Read(buffer, length); return inputBytes.Read(buffer) == buffer.Length;
if (read < length)
{
return false;
}
return true;
} }
} }
} }

View File

@ -312,7 +312,7 @@
bytes.Seek(lastOffset); bytes.Seek(lastOffset);
var buffer = new byte[5]; Span<byte> buffer = stackalloc byte[5];
while (bytes.Read(buffer) == buffer.Length) while (bytes.Read(buffer) == buffer.Length)
{ {
@ -347,10 +347,9 @@
bytes.Seek(lastOffset); bytes.Seek(lastOffset);
} }
bytes.Read(buffer); bytes.Read(buffer);
return false; return false;
} }
} }

View File

@ -103,13 +103,13 @@
// Slide a window of bufferLength bytes across the file allowing for the fact the version could get split by // Slide a window of bufferLength bytes across the file allowing for the fact the version could get split by
// the window (so always ensure an overlap of versionLength bytes between the end of the previous and start of the next buffer). // the window (so always ensure an overlap of versionLength bytes between the end of the previous and start of the next buffer).
var buffer = new byte[bufferLength]; Span<byte> buffer = stackalloc byte[bufferLength];
var currentOffset = startPosition; var currentOffset = startPosition;
int readLength; int readLength;
do do
{ {
readLength = inputBytes.Read(buffer, bufferLength); readLength = inputBytes.Read(buffer);
var content = OtherEncodings.BytesAsLatin1String(buffer); var content = OtherEncodings.BytesAsLatin1String(buffer);