Skip to content

Commit

Permalink
Use stackallocs where possible/sensible
Browse files Browse the repository at this point in the history
  • Loading branch information
Bond-009 committed Feb 12, 2021
1 parent 4a7337b commit 928f647
Show file tree
Hide file tree
Showing 19 changed files with 12,818 additions and 100 deletions.
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

0 comments on commit 928f647

Please sign in to comment.