Skip to content

Commit

Permalink
Spanify IInputBytes
Browse files Browse the repository at this point in the history
  • Loading branch information
iamcarbon authored and BobLd committed Apr 12, 2024
1 parent 775d134 commit e01bf5e
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 77 deletions.
3 changes: 1 addition & 2 deletions src/UglyToad.PdfPig.Core/IInputBytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ public interface IInputBytes : IDisposable
/// Fill the buffer with bytes starting from the current position.
/// </summary>
/// <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>
int Read(byte[] buffer, int? length = null);
int Read(Span<byte> buffer);
}
}
24 changes: 4 additions & 20 deletions src/UglyToad.PdfPig.Core/MemoryInputBytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/// <summary>
/// Input bytes from a byte array.
/// </summary>
public class MemoryInputBytes : IInputBytes
public sealed class MemoryInputBytes : IInputBytes
{
private readonly int upperBound;
private readonly ReadOnlyMemory<byte> memory;
Expand Down Expand Up @@ -73,31 +73,15 @@ public void Seek(long position)
}

/// <inheritdoc />
public int Read(byte[] buffer, int? length = null)
public int Read(Span<byte> buffer)
{
var bytesToRead = buffer.Length;
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)
if (buffer.IsEmpty)
{
return 0;
}

var viableLength = (memory.Length - currentOffset - 1);
var readLength = viableLength < bytesToRead ? viableLength : bytesToRead;
var readLength = viableLength < buffer.Length ? viableLength : buffer.Length;
var startFrom = currentOffset + 1;

memory.Span.Slice(startFrom, readLength).CopyTo(buffer);
Expand Down
28 changes: 23 additions & 5 deletions src/UglyToad.PdfPig.Core/Polyfills/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,37 @@ namespace System.IO;

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
{
stream.Write(buffer, 0, data.Length);
stream.Write(tempBuffer, 0, buffer.Length);
}
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);
}
}
}
Expand Down
25 changes: 5 additions & 20 deletions src/UglyToad.PdfPig.Core/StreamInputBytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/// <summary>
/// Input bytes from a stream.
/// </summary>
public class StreamInputBytes : IInputBytes
public sealed class StreamInputBytes : IInputBytes
{
private readonly Stream stream;
private readonly bool shouldDispose;
Expand Down Expand Up @@ -106,30 +106,15 @@ public void Seek(long position)
}

/// <inheritdoc />
public int Read(byte[] buffer, int? length = null)
public int Read(Span<byte> buffer)
{
var bytesToRead = buffer.Length;
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)
if (buffer.IsEmpty)
{
return 0;
}

var read = stream.Read(buffer, 0, bytesToRead);
int read = stream.Read(buffer);

if (read > 0)
{
CurrentByte = buffer[read - 1];
Expand Down
59 changes: 34 additions & 25 deletions src/UglyToad.PdfPig.Fonts/TrueType/TrueTypeDataBytes.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.TrueType
{
using System;
using System.Buffers.Binary;
using System.Text;
using Core;

Expand All @@ -9,7 +10,6 @@
/// </summary>
public class TrueTypeDataBytes
{
private readonly byte[] internalBuffer = new byte[16];
private readonly IInputBytes inputBytes;

/// <summary>
Expand Down Expand Up @@ -50,29 +50,35 @@ public float Read32Fixed()
/// </summary>
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>
/// Read a <see langword="ushort"/>.
/// </summary>
public ushort ReadUnsignedShort()
{
ReadBuffered(internalBuffer, 2);
Span<byte> buffer = stackalloc byte[2];

ReadBuffered(buffer);

return (ushort)((internalBuffer[0] << 8) + (internalBuffer[1] << 0));
return (ushort)((buffer[0] << 8) + (buffer[1] << 0));
}

/// <summary>
/// Read a <see langword="byte"/>.
/// </summary>
public byte ReadByte()
{
ReadBuffered(internalBuffer, 1);
Span<byte> buffer = stackalloc byte[1];

ReadBuffered(buffer);

return internalBuffer[0];
return buffer[0];
}

/// <summary>
Expand All @@ -99,8 +105,11 @@ public bool TryReadString(int bytesToRead, Encoding encoding, out string result)
return false;
}

byte[] data = new byte[bytesToRead];
if (ReadBuffered(data, bytesToRead))
Span<byte> data = bytesToRead <= 64
? stackalloc byte[bytesToRead]
: new byte[bytesToRead];

if (ReadBuffered(data))
{
result = encoding.GetString(data);
return true;
Expand All @@ -114,19 +123,23 @@ public bool TryReadString(int bytesToRead, Encoding encoding, out string result)
/// </summary>
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>
/// Read an <see langword="int"/>.
/// </summary>
public int ReadSignedInt()
{
ReadBuffered(internalBuffer, 4);
Span<byte> buffer = stackalloc byte[4];

ReadBuffered(buffer);

return (internalBuffer[0] << 24) + (internalBuffer[1] << 16) + (internalBuffer[2] << 8) + (internalBuffer[3] << 0);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
}

/// <summary>
Expand Down Expand Up @@ -175,9 +188,11 @@ public void Seek(long position)
/// </summary>
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;
}
Expand All @@ -204,7 +219,7 @@ public byte[] ReadByteArray(int length)
{
var result = new byte[length];

ReadBuffered(result, length);
ReadBuffered(result);

return result;
}
Expand Down Expand Up @@ -244,15 +259,9 @@ public override string ToString()
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);
if (read < length)
{
return false;
}

return true;
return inputBytes.Read(buffer) == buffer.Length;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ private bool TryBruteForceXrefTableLocate(IInputBytes bytes, long expectedOffset

bytes.Seek(lastOffset);

var buffer = new byte[5];
Span<byte> buffer = stackalloc byte[5];

while (bytes.Read(buffer) == buffer.Length)
{
Expand Down Expand Up @@ -347,9 +347,8 @@ private bool TryBruteForceXrefTableLocate(IInputBytes bytes, long expectedOffset

bytes.Seek(lastOffset);
}
bytes.Read(buffer);


bytes.Read(buffer);

return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ private static bool TryBruteForceVersionLocation(long startPosition, IInputBytes

// 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).
var buffer = new byte[bufferLength];
Span<byte> buffer = stackalloc byte[bufferLength];

var currentOffset = startPosition;
int readLength;
do
{
readLength = inputBytes.Read(buffer, bufferLength);
readLength = inputBytes.Read(buffer);

var content = OtherEncodings.BytesAsLatin1String(buffer);

Expand Down

0 comments on commit e01bf5e

Please sign in to comment.