diff --git a/Directory.Packages.props b/Directory.Packages.props
index 09060b11..498bf1b5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -7,6 +7,7 @@
+
@@ -15,4 +16,4 @@
-
+
\ No newline at end of file
diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs
index a05ad417..6a5c9781 100644
--- a/src/SharpCompress/Archives/Rar/RarArchive.cs
+++ b/src/SharpCompress/Archives/Rar/RarArchive.cs
@@ -14,6 +14,7 @@ namespace SharpCompress.Archives.Rar;
public class RarArchive : AbstractArchive
{
+ private bool _disposed;
internal Lazy UnpackV2017 { get; } =
new(() => new Compressors.Rar.UnpackV2017.Unpack());
internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack());
@@ -25,6 +26,20 @@ public class RarArchive : AbstractArchive
private RarArchive(SourceStream sourceStream)
: base(ArchiveType.Rar, sourceStream) { }
+ public override void Dispose()
+ {
+ if (!_disposed)
+ {
+ if (UnpackV1.IsValueCreated && UnpackV1.Value is IDisposable unpackV1)
+ {
+ unpackV1.Dispose();
+ }
+
+ _disposed = true;
+ base.Dispose();
+ }
+ }
+
protected override IEnumerable LoadEntries(IEnumerable volumes) =>
RarArchiveEntryFactory.GetEntries(this, volumes, ReaderOptions);
diff --git a/src/SharpCompress/BufferPool.cs b/src/SharpCompress/BufferPool.cs
deleted file mode 100644
index 895edc86..00000000
--- a/src/SharpCompress/BufferPool.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Buffers;
-
-namespace SharpCompress.Helpers;
-
-internal static class BufferPool
-{
- ///
- /// gets a buffer from the pool
- ///
- /// size of the buffer
- /// the buffer
- public static byte[] Rent(int bufferSize)
- {
-#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
- return ArrayPool.Shared.Rent(bufferSize);
-#else
- return new byte[bufferSize];
-#endif
- }
-
- ///
- /// returns a buffer to the pool
- ///
- /// the buffer to return
- public static void Return(byte[] buffer)
- {
-#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
- ArrayPool.Shared.Return(buffer);
-#else
- // no-op
-#endif
- }
-}
diff --git a/src/SharpCompress/Compressors/Rar/RarCRC.cs b/src/SharpCompress/Compressors/Rar/RarCRC.cs
index 8f4fb47e..7e6fc6cc 100644
--- a/src/SharpCompress/Compressors/Rar/RarCRC.cs
+++ b/src/SharpCompress/Compressors/Rar/RarCRC.cs
@@ -9,7 +9,7 @@ internal static class RarCRC
public static uint CheckCrc(uint startCrc, byte b) =>
(crcTab[((int)startCrc ^ b) & 0xff] ^ (startCrc >> 8));
- public static uint CheckCrc(uint startCrc, byte[] data, int offset, int count)
+ public static uint CheckCrc(uint startCrc, ReadOnlySpan data, int offset, int count)
{
var size = Math.Min(data.Length - offset, count);
diff --git a/src/SharpCompress/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs
index bf5d3209..073fcaa0 100644
--- a/src/SharpCompress/Compressors/Rar/RarStream.cs
+++ b/src/SharpCompress/Compressors/Rar/RarStream.cs
@@ -1,6 +1,7 @@
#nullable disable
using System;
+using System.Buffers;
using System.IO;
using SharpCompress.Common.Rar.Headers;
@@ -14,7 +15,7 @@ internal class RarStream : Stream
private bool fetch;
- private byte[] tmpBuffer = BufferPool.Rent(65536);
+ private byte[] tmpBuffer = ArrayPool.Shared.Rent(65536);
private int tmpOffset;
private int tmpCount;
@@ -42,7 +43,7 @@ internal class RarStream : Stream
{
if (disposing)
{
- BufferPool.Return(this.tmpBuffer);
+ ArrayPool.Shared.Return(this.tmpBuffer);
this.tmpBuffer = null;
}
isDisposed = true;
@@ -143,11 +144,11 @@ internal class RarStream : Stream
this.tmpBuffer.Length * 2 > this.tmpCount + count
? this.tmpBuffer.Length * 2
: this.tmpCount + count;
- var newBuffer = BufferPool.Rent(newLength);
+ var newBuffer = ArrayPool.Shared.Rent(newLength);
Buffer.BlockCopy(this.tmpBuffer, 0, newBuffer, 0, this.tmpCount);
var oldBuffer = this.tmpBuffer;
this.tmpBuffer = newBuffer;
- BufferPool.Return(oldBuffer);
+ ArrayPool.Shared.Return(oldBuffer);
}
}
}
diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs
index e6d4153d..eb2ddea6 100644
--- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs
+++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs
@@ -1,6 +1,7 @@
#nullable disable
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
@@ -12,14 +13,28 @@ using SharpCompress.Compressors.Rar.VM;
namespace SharpCompress.Compressors.Rar.UnpackV1;
-internal sealed partial class Unpack : BitInput, IRarUnpack
+internal sealed partial class Unpack : BitInput, IRarUnpack, IDisposable
{
private readonly BitInput Inp;
+ private bool disposed;
public Unpack() =>
// to ease in porting Unpack50.cs
Inp = this;
+ public void Dispose()
+ {
+ if (!disposed)
+ {
+ if (!externalWindow)
+ {
+ ArrayPool.Shared.Return(window);
+ window = null;
+ }
+ disposed = true;
+ }
+ }
+
public bool FileExtracted { get; private set; }
public long DestSize
@@ -74,7 +89,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private BlockTypes unpBlockType;
- //private bool externalWindow;
+ private bool externalWindow;
private long writtenFileSize;
@@ -111,15 +126,14 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private void Init(byte[] window)
{
- if (window is null)
+ if (this.window is null && window is null)
{
- this.window = new byte[PackDef.MAXWINSIZE];
+ this.window = ArrayPool.Shared.Rent(PackDef.MAXWINSIZE);
}
- else
+ else if (window is not null)
{
this.window = window;
-
- //externalWindow = true;
+ externalWindow = true;
}
inAddr = 0;
UnpInitData(false);
@@ -175,31 +189,24 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private void UnstoreFile()
{
- var buffer = new byte[0x10000];
- while (true)
+ Span buffer = stackalloc byte[(int)Math.Min(0x10000, destUnpSize)];
+ do
{
- var code = readStream.Read(buffer, 0, (int)Math.Min(buffer.Length, destUnpSize));
+ var code = readStream.Read(buffer);
if (code == 0 || code == -1)
{
break;
}
code = code < destUnpSize ? code : (int)destUnpSize;
- writeStream.Write(buffer, 0, code);
- if (destUnpSize >= 0)
- {
- destUnpSize -= code;
- }
- if (suspended)
- {
- return;
- }
- }
+ writeStream.Write(buffer.Slice(0, code));
+ destUnpSize -= code;
+ } while (!suspended && destUnpSize > 0);
}
private void Unpack29(bool solid)
{
- var DDecode = new int[PackDef.DC];
- var DBits = new byte[PackDef.DC];
+ Span DDecode = stackalloc int[PackDef.DC];
+ Span DBits = stackalloc byte[PackDef.DC];
int Bits;
@@ -859,9 +866,9 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private bool ReadTables()
{
- var bitLength = new byte[PackDef.BC];
+ Span bitLength = stackalloc byte[PackDef.BC];
+ Span table = stackalloc byte[PackDef.HUFF_TABLE_SIZE];
- var table = new byte[PackDef.HUFF_TABLE_SIZE];
if (inAddr > readTop - 25)
{
if (!unpReadBuf())
@@ -989,7 +996,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
// memcpy(unpOldTable,table,sizeof(unpOldTable));
- Buffer.BlockCopy(table, 0, unpOldTable, 0, unpOldTable.Length);
+ table.CopyTo(unpOldTable);
return (true);
}
@@ -1190,7 +1197,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
{
return (false);
}
- var VMCode = new byte[VMCodeSize];
+ Span VMCode = stackalloc byte[VMCodeSize];
for (var I = 0; I < VMCodeSize; I++)
{
if (Inp.Overflow(3))
diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs
index 3a5d008d..e4069c76 100644
--- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs
+++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs
@@ -391,8 +391,8 @@ internal partial class Unpack
private bool ReadTables20()
{
- var BitLength = new byte[PackDef.BC20];
- var Table = new byte[PackDef.MC20 * 4];
+ Span BitLength = stackalloc byte[PackDef.BC20];
+ Span Table = stackalloc byte[PackDef.MC20 * 4];
int TableSize,
N,
I;
diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs
index b501337b..4b16e43d 100644
--- a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs
+++ b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs
@@ -181,7 +181,12 @@ internal static class UnpackUtility
return (dec.DecodeNum[N]);
}
- internal static void makeDecodeTables(byte[] lenTab, int offset, Decode.Decode dec, int size)
+ internal static void makeDecodeTables(
+ Span lenTab,
+ int offset,
+ Decode.Decode dec,
+ int size
+ )
{
Span lenCount = stackalloc int[16];
Span tmpPos = stackalloc int[16];
diff --git a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs
index f758b8a4..0dd3e326 100644
--- a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs
+++ b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs
@@ -776,14 +776,14 @@ internal sealed class RarVM : BitInput
}
}
- public void prepare(byte[] code, int codeSize, VMPreparedProgram prg)
+ public void prepare(ReadOnlySpan code, int codeSize, VMPreparedProgram prg)
{
InitBitInput();
var cpLength = Math.Min(MAX_SIZE, codeSize);
// memcpy(inBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
- Buffer.BlockCopy(code, 0, InBuf, 0, cpLength);
+ code.Slice(0, cpLength).CopyTo(InBuf);
byte xorSum = 0;
for (var i = 1; i < codeSize; i++)
{
@@ -1105,7 +1105,7 @@ internal sealed class RarVM : BitInput
}
}
- private VMStandardFilters IsStandardFilter(byte[] code, int codeSize)
+ private VMStandardFilters IsStandardFilter(ReadOnlySpan code, int codeSize)
{
VMStandardFilterSignature[] stdList =
{
diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs
index b36acd53..96ac0a58 100644
--- a/src/SharpCompress/Readers/AbstractReader.cs
+++ b/src/SharpCompress/Readers/AbstractReader.cs
@@ -44,7 +44,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti
#region IDisposable Members
- public void Dispose()
+ public virtual void Dispose()
{
_entriesForCurrentReadStream?.Dispose();
Volume?.Dispose();
diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs
index 2398cfac..184ba62d 100644
--- a/src/SharpCompress/Readers/Rar/RarReader.cs
+++ b/src/SharpCompress/Readers/Rar/RarReader.cs
@@ -13,6 +13,7 @@ namespace SharpCompress.Readers.Rar;
///
public abstract class RarReader : AbstractReader
{
+ private bool _disposed;
private RarVolume? volume;
private Lazy UnpackV2017 { get; } =
new(() => new Compressors.Rar.UnpackV2017.Unpack());
@@ -21,6 +22,20 @@ public abstract class RarReader : AbstractReader
internal RarReader(ReaderOptions options)
: base(options, ArchiveType.Rar) { }
+ public override void Dispose()
+ {
+ if (!_disposed)
+ {
+ if (UnpackV1.IsValueCreated && UnpackV1.Value is IDisposable unpackV1)
+ {
+ unpackV1.Dispose();
+ }
+
+ _disposed = true;
+ base.Dispose();
+ }
+ }
+
protected abstract void ValidateArchive(RarVolume archive);
public override RarVolume? Volume => volume;
diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj
index 6b31b2a4..4b4909b7 100644
--- a/src/SharpCompress/SharpCompress.csproj
+++ b/src/SharpCompress/SharpCompress.csproj
@@ -33,6 +33,7 @@
true
+
diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json
index d5c6af0b..5b33071a 100644
--- a/src/SharpCompress/packages.lock.json
+++ b/src/SharpCompress/packages.lock.json
@@ -30,6 +30,12 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
+ "System.Buffers": {
+ "type": "Direct",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"System.Memory": {
"type": "Direct",
"requested": "[4.5.5, )",
@@ -76,11 +82,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.5.0",
@@ -129,6 +130,12 @@
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
+ "System.Buffers": {
+ "type": "Direct",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"System.Memory": {
"type": "Direct",
"requested": "[4.5.5, )",
@@ -175,11 +182,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
@@ -216,6 +218,12 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
+ "System.Buffers": {
+ "type": "Direct",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"System.Text.Encoding.CodePages": {
"type": "Direct",
"requested": "[8.0.0, )",
@@ -245,11 +253,6 @@
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
@@ -283,6 +286,12 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
+ "System.Buffers": {
+ "type": "Direct",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.1, )",
@@ -317,6 +326,12 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
+ "System.Buffers": {
+ "type": "Direct",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.1, )",
@@ -335,4 +350,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/SharpCompress.Test/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json
index 7e146431..94f193fc 100644
--- a/tests/SharpCompress.Test/packages.lock.json
+++ b/tests/SharpCompress.Test/packages.lock.json
@@ -97,11 +97,6 @@
"System.Reflection.Metadata": "1.6.0"
}
},
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "1.5.0",
@@ -182,6 +177,7 @@
"type": "Project",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "[8.0.0, )",
+ "System.Buffers": "[4.6.0, )",
"System.Memory": "[4.5.5, )",
"System.Text.Encoding.CodePages": "[8.0.0, )",
"ZstdSharp.Port": "[0.8.1, )"
@@ -196,6 +192,12 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
+ "System.Buffers": {
+ "type": "CentralTransitive",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"System.Memory": {
"type": "CentralTransitive",
"requested": "[4.5.5, )",
@@ -394,9 +396,16 @@
"sharpcompress": {
"type": "Project",
"dependencies": {
+ "System.Buffers": "[4.6.0, )",
"ZstdSharp.Port": "[0.8.1, )"
}
},
+ "System.Buffers": {
+ "type": "CentralTransitive",
+ "requested": "[4.6.0, )",
+ "resolved": "4.6.0",
+ "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
+ },
"ZstdSharp.Port": {
"type": "CentralTransitive",
"requested": "[0.8.1, )",