summary refs log tree commit diff
path: root/LibGit/Extensions
diff options
context:
space:
mode:
Diffstat (limited to 'LibGit/Extensions')
-rw-r--r--LibGit/Extensions/StreamExtensions.cs101
1 files changed, 79 insertions, 22 deletions
diff --git a/LibGit/Extensions/StreamExtensions.cs b/LibGit/Extensions/StreamExtensions.cs

index 41e4b4f..90bd35a 100644 --- a/LibGit/Extensions/StreamExtensions.cs +++ b/LibGit/Extensions/StreamExtensions.cs
@@ -1,4 +1,5 @@ using System.IO.Compression; +using System.Runtime.InteropServices; namespace LibGit.Extensions; @@ -53,18 +54,25 @@ public static class StreamExtensions { if (!stream.CanRead) throw new InvalidOperationException("Can't read a non-readable stream"); - if (!stream.CanSeek) - throw new InvalidOperationException("Can't read a non-seekable stream"); - for (long i = 0; i < count; i++) + var buffer = new byte[count]; + var readCount = stream.Read(buffer, 0, (int)count); + for (int i = 0; i < readCount; i++) { - int read = stream.ReadByte(); - if (read == -1) - yield break; - yield return (byte)read; + yield return buffer[i]; } } + public static byte[] ReadBlock(this Stream stream, int count) + { + if (!stream.CanRead) + throw new InvalidOperationException("Can't read a non-readable stream"); + + Span<byte> buffer = stackalloc byte[count]; + stream.ReadExactly(buffer); + return buffer.ToArray(); + } + public static bool StartsWith(this Stream stream, IEnumerable<byte> sequence) { if (!stream.CanRead) @@ -172,13 +180,25 @@ public static class StreamExtensions if (!stream.CanRead) throw new InvalidOperationException("Can't read a non-readable stream"); - var bytes = stream.ReadBytes(4).ToArray(); + Span<byte> b = stackalloc byte[4]; + stream.ReadExactly(b); + return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); + } - if (BitConverter.IsLittleEndian) - Array.Reverse(bytes); + public static int[] MultiReadInt32BE(this Stream stream, int count) + { + if (!stream.CanRead) + throw new InvalidOperationException("Can't read a non-readable stream"); - // Console.WriteLine("ReadInt32BE: " + bytes.AsHexString() + " => " + BitConverter.ToInt32(bytes)); - return BitConverter.ToInt32(bytes); + Span<byte> b = stackalloc byte[4 * count]; + stream.ReadExactly(b); + int[] results = new int[count]; + for (int i = 0; i < count; i++) + { + results[i] = (b[i * 4 + 0] << 24) | (b[i * 4 + 1] << 16) | (b[i * 4 + 2] << 8) | b[i * 4 + 3]; + } + + return results; } public static uint ReadUInt32BE(this Stream stream) @@ -186,13 +206,25 @@ public static class StreamExtensions if (!stream.CanRead) throw new InvalidOperationException("Can't read a non-readable stream"); - var bytes = stream.ReadBytes(4).ToArray(); + Span<byte> b = stackalloc byte[4]; + stream.ReadExactly(b); + return (uint)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); + } + + public static uint[] MultiReadUInt32BE(this Stream stream, int count) + { + if (!stream.CanRead) + throw new InvalidOperationException("Can't read a non-readable stream"); - if (BitConverter.IsLittleEndian) - Array.Reverse(bytes); + Span<byte> b = count >= 32767 ? new byte[4 * count] : stackalloc byte[4 * count]; + stream.ReadExactly(b); + uint[] results = new uint[count]; + for (int i = 0; i < count; i++) + { + results[i] = (uint)((b[i * 4 + 0] << 24) | (b[i * 4 + 1] << 16) | (b[i * 4 + 2] << 8) | b[i * 4 + 3]); + } - // Console.WriteLine("ReadUInt32BE: " + bytes.AsHexString() + " => " + BitConverter.ToUInt32(bytes)); - return BitConverter.ToUInt32(bytes); + return results; } public static ulong ReadUInt64BE(this Stream stream) @@ -200,13 +232,38 @@ public static class StreamExtensions if (!stream.CanRead) throw new InvalidOperationException("Can't read a non-readable stream"); - var bytes = stream.ReadBytes(8).ToArray(); + Span<byte> b = stackalloc byte[8]; + stream.ReadExactly(b); + return ((ulong)b[0] << 56) | ((ulong)b[1] << 48) | ((ulong)b[2] << 40) | ((ulong)b[3] << 32) | + ((ulong)b[4] << 24) | ((ulong)b[5] << 16) | ((ulong)b[6] << 8) | b[7]; + } - if (BitConverter.IsLittleEndian) - Array.Reverse(bytes); + public static ulong[] MultiReadUInt64BE(this Stream stream, int count) + { + if (!stream.CanRead) + throw new InvalidOperationException("Can't read a non-readable stream"); + + Span<byte> b = count >= 16384 ? new byte[8 * count] : stackalloc byte[8 * count]; + stream.ReadExactly(b); + ulong[] results = new ulong[count]; + for (int i = 0; i < count; i++) + { + results[i] = ((ulong)b[i * 8 + 0] << 56) | ((ulong)b[i * 8 + 1] << 48) | ((ulong)b[i * 8 + 2] << 40) | ((ulong)b[i * 8 + 3] << 32) | + ((ulong)b[i * 8 + 4] << 24) | ((ulong)b[i * 8 + 5] << 16) | ((ulong)b[i * 8 + 6] << 8) | b[i * 8 + 7]; + } + + return results; + } + + public static T[] MultiReadInlineArray<T>(this Stream stream, int count) where T : unmanaged + { + if (!stream.CanRead) + throw new InvalidOperationException("Can't read a non-readable stream"); - // Console.WriteLine("ReadUInt64BE: " + bytes.AsHexString() + " => " + BitConverter.ToUInt64(bytes)); - return BitConverter.ToUInt64(bytes); + Span<T> buffer = count >= 8192 ? new T[count] : stackalloc T[count]; + Span<byte> byteBuffer = MemoryMarshal.AsBytes(buffer); + stream.ReadExactly(byteBuffer); + return buffer.ToArray(); } //read variable length number