diff --git a/src/UglyToad.PdfPig.Core/IInputBytes.cs b/src/UglyToad.PdfPig.Core/IInputBytes.cs
index efdf6d9c..834f5f39 100644
--- a/src/UglyToad.PdfPig.Core/IInputBytes.cs
+++ b/src/UglyToad.PdfPig.Core/IInputBytes.cs
@@ -47,8 +47,7 @@
/// Fill the buffer with bytes starting from the current position.
///
/// A buffer with a length corresponding to the number of bytes to read.
- /// Optional override for the number of bytes to read.
/// The number of bytes successfully read.
- int Read(byte[] buffer, int? length = null);
+ int Read(Span buffer);
}
}
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig.Core/MemoryInputBytes.cs b/src/UglyToad.PdfPig.Core/MemoryInputBytes.cs
index ff91ce8d..e4bac1ee 100644
--- a/src/UglyToad.PdfPig.Core/MemoryInputBytes.cs
+++ b/src/UglyToad.PdfPig.Core/MemoryInputBytes.cs
@@ -7,7 +7,7 @@
///
/// Input bytes from a byte array.
///
- public class MemoryInputBytes : IInputBytes
+ public sealed class MemoryInputBytes : IInputBytes
{
private readonly int upperBound;
private readonly ReadOnlyMemory memory;
@@ -73,31 +73,15 @@
}
///
- public int Read(byte[] buffer, int? length = null)
+ public int Read(Span 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);
diff --git a/src/UglyToad.PdfPig.Core/Polyfills/StreamExtensions.cs b/src/UglyToad.PdfPig.Core/Polyfills/StreamExtensions.cs
index 2792cfed..cb2daf76 100644
--- a/src/UglyToad.PdfPig.Core/Polyfills/StreamExtensions.cs
+++ b/src/UglyToad.PdfPig.Core/Polyfills/StreamExtensions.cs
@@ -6,19 +6,37 @@ using System.Buffers;
internal static class StreamExtensions
{
- public static void Write(this Stream stream, ReadOnlySpan data)
+ public static void Write(this Stream stream, ReadOnlySpan buffer)
{
- var buffer = ArrayPool.Shared.Rent(data.Length);
+ var tempBuffer = ArrayPool.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.Shared.Return(buffer);
+ ArrayPool.Shared.Return(tempBuffer);
+ }
+ }
+
+ public static int Read(this Stream stream, Span buffer)
+ {
+ var tempBuffer = ArrayPool.Shared.Rent(buffer.Length);
+
+ try
+ {
+ int read = stream.Read(tempBuffer, 0, buffer.Length);
+
+ tempBuffer.AsSpan(0, read).CopyTo(buffer);
+
+ return read;
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(tempBuffer);
}
}
}
diff --git a/src/UglyToad.PdfPig.Core/StreamInputBytes.cs b/src/UglyToad.PdfPig.Core/StreamInputBytes.cs
index 562432f2..ab1ef057 100644
--- a/src/UglyToad.PdfPig.Core/StreamInputBytes.cs
+++ b/src/UglyToad.PdfPig.Core/StreamInputBytes.cs
@@ -7,7 +7,7 @@
///
/// Input bytes from a stream.
///
- public class StreamInputBytes : IInputBytes
+ public sealed class StreamInputBytes : IInputBytes
{
private readonly Stream stream;
private readonly bool shouldDispose;
@@ -106,30 +106,15 @@
}
///
- public int Read(byte[] buffer, int? length = null)
+ public int Read(Span 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];
diff --git a/src/UglyToad.PdfPig.Fonts/TrueType/TrueTypeDataBytes.cs b/src/UglyToad.PdfPig.Fonts/TrueType/TrueTypeDataBytes.cs
index f01b91c7..3dc4d55e 100644
--- a/src/UglyToad.PdfPig.Fonts/TrueType/TrueTypeDataBytes.cs
+++ b/src/UglyToad.PdfPig.Fonts/TrueType/TrueTypeDataBytes.cs
@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.TrueType
{
using System;
+ using System.Buffers.Binary;
using System.Text;
using Core;
@@ -9,7 +10,6 @@
///
public class TrueTypeDataBytes
{
- private readonly byte[] internalBuffer = new byte[16];
private readonly IInputBytes inputBytes;
///
@@ -50,9 +50,11 @@
///
public short ReadSignedShort()
{
- ReadBuffered(internalBuffer, 2);
+ Span buffer = stackalloc byte[2];
- return unchecked((short)((internalBuffer[0] << 8) + (internalBuffer[1] << 0)));
+ ReadBuffered(buffer);
+
+ return unchecked((short)((buffer[0] << 8) + (buffer[1] << 0)));
}
///
@@ -60,9 +62,11 @@
///
public ushort ReadUnsignedShort()
{
- ReadBuffered(internalBuffer, 2);
+ Span buffer = stackalloc byte[2];
- return (ushort)((internalBuffer[0] << 8) + (internalBuffer[1] << 0));
+ ReadBuffered(buffer);
+
+ return (ushort)((buffer[0] << 8) + (buffer[1] << 0));
}
///
@@ -70,9 +74,11 @@
///
public byte ReadByte()
{
- ReadBuffered(internalBuffer, 1);
+ Span buffer = stackalloc byte[1];
- return internalBuffer[0];
+ ReadBuffered(buffer);
+
+ return buffer[0];
}
///
@@ -99,8 +105,11 @@
return false;
}
- byte[] data = new byte[bytesToRead];
- if (ReadBuffered(data, bytesToRead))
+ Span data = bytesToRead <= 64
+ ? stackalloc byte[bytesToRead]
+ : new byte[bytesToRead];
+
+ if (ReadBuffered(data))
{
result = encoding.GetString(data);
return true;
@@ -114,9 +123,11 @@
///
public uint ReadUnsignedInt()
{
- ReadBuffered(internalBuffer, 4);
+ Span 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);
}
///
@@ -124,9 +135,11 @@
///
public int ReadSignedInt()
{
- ReadBuffered(internalBuffer, 4);
+ Span buffer = stackalloc byte[4];
- return (internalBuffer[0] << 24) + (internalBuffer[1] << 16) + (internalBuffer[2] << 8) + (internalBuffer[3] << 0);
+ ReadBuffered(buffer);
+
+ return BinaryPrimitives.ReadInt32BigEndian(buffer);
}
///
@@ -175,9 +188,11 @@
///
public int ReadSignedByte()
{
- ReadBuffered(internalBuffer, 1);
+ Span buffer = stackalloc byte[1];
- var signedByte = internalBuffer[0];
+ ReadBuffered(buffer);
+
+ var signedByte = buffer[0];
return signedByte < 127 ? signedByte : signedByte - 256;
}
@@ -204,7 +219,7 @@
{
var result = new byte[length];
- ReadBuffered(result, length);
+ ReadBuffered(result);
return result;
}
@@ -244,15 +259,9 @@
return $"@: {Position} of {inputBytes.Length} bytes.";
}
- private bool ReadBuffered(byte[] buffer, int length)
+ private bool ReadBuffered(Span buffer)
{
- var read = inputBytes.Read(buffer, length);
- if (read < length)
- {
- return false;
- }
-
- return true;
+ return inputBytes.Read(buffer) == buffer.Length;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs b/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs
index 2bb7ed34..8541b53a 100644
--- a/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs
+++ b/src/UglyToad.PdfPig/Parser/FileStructure/CrossReferenceParser.cs
@@ -312,7 +312,7 @@
bytes.Seek(lastOffset);
- var buffer = new byte[5];
+ Span buffer = stackalloc byte[5];
while (bytes.Read(buffer) == buffer.Length)
{
@@ -347,10 +347,9 @@
bytes.Seek(lastOffset);
}
+
bytes.Read(buffer);
-
-
return false;
}
}
diff --git a/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs b/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs
index 3f8f9ab5..6b2ccb75 100644
--- a/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs
+++ b/src/UglyToad.PdfPig/Parser/FileStructure/FileHeaderParser.cs
@@ -103,13 +103,13 @@
// 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 buffer = stackalloc byte[bufferLength];
var currentOffset = startPosition;
int readLength;
do
{
- readLength = inputBytes.Read(buffer, bufferLength);
+ readLength = inputBytes.Read(buffer);
var content = OtherEncodings.BytesAsLatin1String(buffer);