Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use stackallocs where possible/sensible #568

Merged
merged 1 commit into from Feb 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/SharpCompress/Archives/GZip/GZipArchive.cs
Expand Up @@ -98,7 +98,7 @@ public void SaveTo(FileInfo fileInfo)
public static bool IsGZipFile(Stream stream)
{
// read the header on the first read
byte[] header = new byte[10];
Span<byte> header = stackalloc byte[10];

// workitem 8501: handle edge case (decompress empty stream)
if (!stream.ReadFully(header))
Expand Down
4 changes: 2 additions & 2 deletions src/SharpCompress/Common/GZip/GZipFilePart.cs
Expand Up @@ -110,13 +110,13 @@ private void ReadAndValidateGzipHeader()

private string ReadZeroTerminatedString(Stream stream)
{
byte[] buf1 = new byte[1];
Span<byte> buf1 = stackalloc byte[1];
var list = new List<byte>();
bool done = false;
do
{
// workitem 7740
int n = stream.Read(buf1, 0, 1);
int n = stream.Read(buf1);
if (n != 1)
{
throw new ZlibException("Unexpected EOF reading GZIP header.");
Expand Down
4 changes: 2 additions & 2 deletions src/SharpCompress/Common/Rar/RarCryptoWrapper.cs
Expand Up @@ -50,11 +50,11 @@ public int ReadAndDecrypt(byte[] buffer, int offset, int count)
if (sizeToRead > 0)
{
int alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf);
byte[] cipherText = new byte[RarRijndael.CRYPTO_BLOCK_SIZE];
Span<byte> cipherText = stackalloc byte[RarRijndael.CRYPTO_BLOCK_SIZE];
for (int i = 0; i < alignedSize / 16; i++)
{
//long ax = System.currentTimeMillis();
_actualStream.Read(cipherText, 0, RarRijndael.CRYPTO_BLOCK_SIZE);
_actualStream.Read(cipherText);

var readBytes = _rijndael.ProcessBlock(cipherText);
foreach (var readByte in readBytes)
Expand Down
3 changes: 2 additions & 1 deletion src/SharpCompress/Common/SevenZip/ArchiveReader.cs
Expand Up @@ -1517,6 +1517,7 @@ public void Extract(ArchiveDatabase db, int[] indices)
}
}

byte[] buffer = null;
foreach (CExtractFolderInfo efi in extractFolderInfoVector)
{
int startIndex;
Expand Down Expand Up @@ -1553,7 +1554,7 @@ public void Extract(ArchiveDatabase db, int[] indices)

Stream s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes,
folderInfo, db.PasswordProvider);
byte[] buffer = new byte[4 << 10];
buffer ??= new byte[4 << 10];
for (; ; )
{
int processed = s.Read(buffer, 0, buffer.Length);
Expand Down
2 changes: 1 addition & 1 deletion src/SharpCompress/Common/Tar/Headers/TarHeader.cs
Expand Up @@ -97,7 +97,7 @@ private void WriteLongFilenameHeader(Stream output)
{
numPaddingBytes = BLOCK_SIZE;
}
output.Write(new byte[numPaddingBytes], 0, numPaddingBytes);
output.Write(stackalloc byte[numPaddingBytes]);
}

internal bool Read(BinaryReader reader)
Expand Down
2 changes: 1 addition & 1 deletion src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs
Expand Up @@ -75,7 +75,7 @@ protected override void Dispose(bool disposing)
if (disposing)
{
//read out last 10 auth bytes
var ten = new byte[10];
Span<byte> ten = stackalloc byte[10];
_stream.ReadFully(ten);
_stream.Dispose();
}
Expand Down
2 changes: 1 addition & 1 deletion src/SharpCompress/Common/Zip/ZipFilePart.cs
Expand Up @@ -93,7 +93,7 @@ protected Stream CreateDecompressionStream(Stream stream, ZipCompressionMethod m
}
case ZipCompressionMethod.PPMd:
{
var props = new byte[2];
Span<byte> props = stackalloc byte[2];
stream.ReadFully(props);
return new PpmdStream(new PpmdProperties(props), stream, false);
}
Expand Down
12 changes: 5 additions & 7 deletions src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs
Expand Up @@ -256,17 +256,15 @@ private void finish()
}

// Read and potentially verify the GZIP trailer: CRC32 and size mod 2^32
byte[] trailer = new byte[8];
Span<byte> trailer = stackalloc byte[8];

// workitem 8679
if (_z.AvailableBytesIn != 8)
{
// Make sure we have read to the end of the stream
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, _z.AvailableBytesIn);
_z.InputBuffer.AsSpan(_z.NextIn, _z.AvailableBytesIn).CopyTo(trailer);
int bytesNeeded = 8 - _z.AvailableBytesIn;
int bytesRead = _stream.Read(trailer,
_z.AvailableBytesIn,
bytesNeeded);
int bytesRead = _stream.Read(trailer.Slice(_z.AvailableBytesIn, bytesNeeded));
if (bytesNeeded != bytesRead)
{
throw new ZlibException(String.Format(
Expand All @@ -276,12 +274,12 @@ private void finish()
}
else
{
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length);
_z.InputBuffer.AsSpan(_z.NextIn, trailer.Length).CopyTo(trailer);
}

Int32 crc32_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer);
Int32 crc32_actual = crc.Crc32Result;
Int32 isize_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer.AsSpan(4));
Int32 isize_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer.Slice(4));
Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF);

if (crc32_actual != crc32_expected)
Expand Down
8 changes: 4 additions & 4 deletions src/SharpCompress/Compressors/LZMA/LZipStream.cs
Expand Up @@ -59,16 +59,16 @@ public void Finish()
crc32Stream.Dispose();
var compressedCount = _countingWritableSubStream!.Count;

byte[] intBuf = new byte[8];
Span<byte> intBuf = stackalloc byte[8];
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, crc32Stream.Crc);
_countingWritableSubStream.Write(intBuf, 0, 4);
_countingWritableSubStream.Write(intBuf.Slice(0, 4));

BinaryPrimitives.WriteInt64LittleEndian(intBuf, _writeCount);
_countingWritableSubStream.Write(intBuf, 0, 8);
_countingWritableSubStream.Write(intBuf);

//total with headers
BinaryPrimitives.WriteUInt64LittleEndian(intBuf, compressedCount + 6 + 20);
_countingWritableSubStream.Write(intBuf, 0, 8);
_countingWritableSubStream.Write(intBuf);
}
_finished = true;
}
Expand Down
8 changes: 6 additions & 2 deletions src/SharpCompress/Compressors/PPMd/PpmdProperties.cs
Expand Up @@ -31,7 +31,11 @@ internal PpmdProperties(int allocatorSize, int modelOrder, ModelRestorationMetho
public PpmdVersion Version { get; } = PpmdVersion.I1;
internal ModelRestorationMethod RestorationMethod { get; }

public PpmdProperties(byte[] properties)
public PpmdProperties(byte[] properties) : this(properties.AsSpan())
{
}

public PpmdProperties(ReadOnlySpan<byte> properties)
{
if (properties.Length == 2)
{
Expand All @@ -43,7 +47,7 @@ public PpmdProperties(byte[] properties)
else if (properties.Length == 5)
{
Version = PpmdVersion.H7Z;
AllocatorSize = BinaryPrimitives.ReadInt32LittleEndian(properties.AsSpan(1));
AllocatorSize = BinaryPrimitives.ReadInt32LittleEndian(properties.Slice(1));
ModelOrder = properties[0];
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/SharpCompress/Compressors/Xz/BinaryUtils.cs
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using System.IO;

namespace SharpCompress.Compressors.Xz
Expand All @@ -8,7 +9,7 @@ public static class BinaryUtils
public static int ReadLittleEndianInt32(this BinaryReader reader)
{
byte[] bytes = reader.ReadBytes(4);
return (bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24));
return BinaryPrimitives.ReadInt32LittleEndian(bytes);
}

internal static uint ReadLittleEndianUInt32(this BinaryReader reader)
Expand All @@ -17,13 +18,13 @@ internal static uint ReadLittleEndianUInt32(this BinaryReader reader)
}
public static int ReadLittleEndianInt32(this Stream stream)
{
byte[] bytes = new byte[4];
Span<byte> bytes = stackalloc byte[4];
var read = stream.ReadFully(bytes);
if (!read)
{
throw new EndOfStreamException();
}
return (bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24));
return BinaryPrimitives.ReadInt32LittleEndian(bytes);
}

internal static uint ReadLittleEndianUInt32(this Stream stream)
Expand Down
11 changes: 5 additions & 6 deletions src/SharpCompress/Compressors/Xz/Crc32.cs
@@ -1,7 +1,6 @@
#nullable disable

using System;
using System.Collections.Generic;

namespace SharpCompress.Compressors.Xz
{
Expand All @@ -24,7 +23,7 @@ public static UInt32 Compute(UInt32 seed, byte[] buffer)

public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
{
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
return ~CalculateHash(InitializeTable(polynomial), seed, buffer);
}

private static UInt32[] InitializeTable(UInt32 polynomial)
Expand Down Expand Up @@ -61,16 +60,16 @@ private static UInt32[] InitializeTable(UInt32 polynomial)
return createTable;
}

private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, IList<byte> buffer, int start, int size)
private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, ReadOnlySpan<byte> buffer)
{
var crc = seed;
for (var i = start; i < size - start; i++)
int len = buffer.Length;
for (var i = 0; i < len; i++)
{
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
crc = (crc >> 8) ^ table[(buffer[i] ^ crc) & 0xff];
}

return crc;
}

}
}
8 changes: 4 additions & 4 deletions src/SharpCompress/Compressors/Xz/Crc64.cs
Expand Up @@ -22,14 +22,14 @@ public static UInt64 Compute(UInt64 seed, byte[] buffer)
{
Table ??= CreateTable(Iso3309Polynomial);

return CalculateHash(seed, Table, buffer, 0, buffer.Length);
return CalculateHash(seed, Table, buffer);
}

public static UInt64 CalculateHash(UInt64 seed, UInt64[] table, IList<byte> buffer, int start, int size)
public static UInt64 CalculateHash(UInt64 seed, UInt64[] table, ReadOnlySpan<byte> buffer)
{
var crc = seed;

for (var i = start; i < size; i++)
int len = buffer.Length;
for (var i = 0; i < len; i++)
{
unchecked
{
Expand Down
4 changes: 2 additions & 2 deletions src/SharpCompress/Polyfills/StreamExtensions.cs
Expand Up @@ -12,7 +12,7 @@ public static int Read(this Stream stream, Span<byte> buffer)

try
{
int read = stream.Read(temp, 0, buffer.Length);
int read = stream.Read(buffer);

temp.AsSpan(0, read).CopyTo(buffer);

Expand Down Expand Up @@ -42,4 +42,4 @@ public static void Write(this Stream stream, ReadOnlySpan<byte> buffer)
}
}

#endif
#endif
4 changes: 2 additions & 2 deletions src/SharpCompress/Utility.cs
Expand Up @@ -281,11 +281,11 @@ private static byte[] GetTransferByteArray()
return ArrayPool<byte>.Shared.Rent(81920);
}

public static bool ReadFully(this Stream stream, byte[] buffer)
public static bool ReadFully(this Stream stream, Span<byte> buffer)
{
int total = 0;
int read;
while ((read = stream.Read(buffer, total, buffer.Length - total)) > 0)
while ((read = stream.Read(buffer.Slice(total, buffer.Length - total))) > 0)
{
total += read;
if (total >= buffer.Length)
Expand Down
4 changes: 2 additions & 2 deletions src/SharpCompress/Writers/Tar/TarWriter.cs
Expand Up @@ -99,7 +99,7 @@ private void PadTo512(long size, bool forceZeros)
return;
}
zeros = 512 - zeros;
OutputStream.Write(new byte[zeros], 0, zeros);
OutputStream.Write(stackalloc byte[zeros]);
}

protected override void Dispose(bool isDisposing)
Expand Down Expand Up @@ -128,4 +128,4 @@ protected override void Dispose(bool isDisposing)
base.Dispose(isDisposing);
}
}
}
}
44 changes: 22 additions & 22 deletions src/SharpCompress/Writers/Zip/ZipCentralDirectoryEntry.cs
Expand Up @@ -71,60 +71,60 @@ internal uint Write(Stream outputStream)
usedCompression = ZipCompressionMethod.None;
}

byte[] intBuf = new byte[] { 80, 75, 1, 2, version, 0, version, 0 };
Span<byte> intBuf = stackalloc byte[] { 80, 75, 1, 2, version, 0, version, 0 };
//constant sig, then version made by, then version to extract
outputStream.Write(intBuf, 0, 8);
outputStream.Write(intBuf);

BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)flags);
outputStream.Write(intBuf, 0, 2);
outputStream.Write(intBuf.Slice(0, 2));
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)usedCompression);
outputStream.Write(intBuf, 0, 2); // zipping method
outputStream.Write(intBuf.Slice(0, 2)); // zipping method
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, ModificationTime.DateTimeToDosTime());
outputStream.Write(intBuf, 0, 4);
outputStream.Write(intBuf.Slice(0, 4));

// zipping date and time
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, Crc);
outputStream.Write(intBuf, 0, 4); // file CRC
outputStream.Write(intBuf.Slice(0, 4)); // file CRC
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, compressedvalue);
outputStream.Write(intBuf, 0, 4); // compressed file size
outputStream.Write(intBuf.Slice(0, 4)); // compressed file size
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, decompressedvalue);
outputStream.Write(intBuf, 0, 4); // uncompressed file size
outputStream.Write(intBuf.Slice(0, 4)); // uncompressed file size
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)encodedFilename.Length);
outputStream.Write(intBuf, 0, 2); // Filename in zip
outputStream.Write(intBuf.Slice(0, 2)); // Filename in zip
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)extralength);
outputStream.Write(intBuf, 0, 2); // extra length
outputStream.Write(intBuf.Slice(0, 2)); // extra length
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)encodedComment.Length);
outputStream.Write(intBuf, 0, 2);
outputStream.Write(intBuf.Slice(0, 2));

BinaryPrimitives.WriteUInt16LittleEndian(intBuf, 0);
outputStream.Write(intBuf, 0, 2); // disk=0
outputStream.Write(intBuf.Slice(0, 2)); // disk=0
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)flags);
outputStream.Write(intBuf, 0, 2); // file type: binary
outputStream.Write(intBuf.Slice(0, 2)); // file type: binary
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)flags);
outputStream.Write(intBuf, 0, 2); // Internal file attributes
outputStream.Write(intBuf.Slice(0, 2)); // Internal file attributes
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, 0x8100);
outputStream.Write(intBuf, 0, 2);
outputStream.Write(intBuf.Slice(0, 2));

// External file attributes (normal/readable)
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, headeroffsetvalue);
outputStream.Write(intBuf, 0, 4); // Offset of header
outputStream.Write(intBuf.Slice(0, 4)); // Offset of header

outputStream.Write(encodedFilename, 0, encodedFilename.Length);
if (zip64)
{
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, 0x0001);
outputStream.Write(intBuf, 0, 2);
outputStream.Write(intBuf.Slice(0, 2));
BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)(extralength - 4));
outputStream.Write(intBuf, 0, 2);
outputStream.Write(intBuf.Slice(0, 2));

BinaryPrimitives.WriteUInt64LittleEndian(intBuf, Decompressed);
outputStream.Write(intBuf, 0, 8);
outputStream.Write(intBuf);
BinaryPrimitives.WriteUInt64LittleEndian(intBuf, Compressed);
outputStream.Write(intBuf, 0, 8);
outputStream.Write(intBuf);
BinaryPrimitives.WriteUInt64LittleEndian(intBuf, HeaderOffset);
outputStream.Write(intBuf, 0, 8);
outputStream.Write(intBuf);
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, 0);
outputStream.Write(intBuf, 0, 4); // VolumeNumber = 0
outputStream.Write(intBuf.Slice(0, 4)); // VolumeNumber = 0
}

outputStream.Write(encodedComment, 0, encodedComment.Length);
Expand Down