diff --git a/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs b/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs
index 7932caad..dbc1d170 100644
--- a/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs
+++ b/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs
@@ -2,6 +2,7 @@
#if !NO_FILE
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
@@ -18,7 +19,7 @@ namespace SharpCompress.Archives.Rar
: base(StreamingMode.Seekable, fileInfo.OpenRead(), FixOptions(options))
{
FileInfo = fileInfo;
- FileParts = GetVolumeFileParts().ToReadOnly();
+ FileParts = GetVolumeFileParts().ToArray().ToReadOnly();
}
private static ReaderOptions FixOptions(ReaderOptions options)
@@ -43,4 +44,4 @@ namespace SharpCompress.Archives.Rar
}
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/SharpCompress/Buffers/ArrayPool.cs b/src/SharpCompress/Buffers/ArrayPool.cs
deleted file mode 100644
index d81ed4c0..00000000
--- a/src/SharpCompress/Buffers/ArrayPool.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-#if NETCORE
-using System.Runtime.CompilerServices;
-using System.Threading;
-
-namespace SharpCompress.Buffers
-{
- ///
- /// Provides a resource pool that enables reusing instances of type .
- ///
- ///
- ///
- /// Renting and returning buffers with an can increase performance
- /// in situations where arrays are created and destroyed frequently, resulting in significant
- /// memory pressure on the garbage collector.
- ///
- ///
- /// This class is thread-safe. All members may be used by multiple threads concurrently.
- ///
- ///
- internal abstract class ArrayPool
- {
- /// The lazily-initialized shared pool instance.
- private static ArrayPool s_sharedInstance = null;
-
- ///
- /// Retrieves a shared instance.
- ///
- ///
- /// The shared pool provides a default implementation of
- /// that's intended for general applicability. It maintains arrays of multiple sizes, and
- /// may hand back a larger array than was actually requested, but will never hand back a smaller
- /// array than was requested. Renting a buffer from it with will result in an
- /// existing buffer being taken from the pool if an appropriate buffer is available or in a new
- /// buffer being allocated if one is not available.
- ///
- public static ArrayPool Shared
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get { return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated(); }
- }
-
- /// Ensures that has been initialized to a pool and returns it.
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static ArrayPool EnsureSharedCreated()
- {
- Interlocked.CompareExchange(ref s_sharedInstance, Create(), null);
- return s_sharedInstance;
- }
-
- ///
- /// Creates a new instance using default configuration options.
- ///
- /// A new instance.
- public static ArrayPool Create()
- {
- return new DefaultArrayPool();
- }
-
- ///
- /// Creates a new instance using custom configuration options.
- ///
- /// The maximum length of array instances that may be stored in the pool.
- ///
- /// The maximum number of array instances that may be stored in each bucket in the pool. The pool
- /// groups arrays of similar lengths into buckets for faster access.
- ///
- /// A new instance with the specified configuration options.
- ///
- /// The created pool will group arrays into buckets, with no more than
- /// in each bucket and with those arrays not exceeding in length.
- ///
- public static ArrayPool Create(int maxArrayLength, int maxArraysPerBucket)
- {
- return new DefaultArrayPool(maxArrayLength, maxArraysPerBucket);
- }
-
- ///
- /// Retrieves a buffer that is at least the requested length.
- ///
- /// The minimum length of the array needed.
- ///
- /// An that is at least in length.
- ///
- ///
- /// This buffer is loaned to the caller and should be returned to the same pool via
- /// so that it may be reused in subsequent usage of .
- /// It is not a fatal error to not return a rented buffer, but failure to do so may lead to
- /// decreased application performance, as the pool may need to create a new buffer to replace
- /// the one lost.
- ///
- public abstract T[] Rent(int minimumLength);
-
- ///
- /// Returns to the pool an array that was previously obtained via on the same
- /// instance.
- ///
- ///
- /// The buffer previously obtained from to return to the pool.
- ///
- ///
- /// If true and if the pool will store the buffer to enable subsequent reuse,
- /// will clear of its contents so that a subsequent consumer via
- /// will not see the previous consumer's content. If false or if the pool will release the buffer,
- /// the array's contents are left unchanged.
- ///
- ///
- /// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer
- /// and must not use it. The reference returned from a given call to must only be
- /// returned via once. The default
- /// may hold onto the returned buffer in order to rent it again, or it may release the returned buffer
- /// if it's determined that the pool already has enough buffers stored.
- ///
- public abstract void Return(T[] array, bool clearArray = false);
- }
-}
-#endif
\ No newline at end of file
diff --git a/src/SharpCompress/Buffers/DefaultArrayPool.cs b/src/SharpCompress/Buffers/DefaultArrayPool.cs
deleted file mode 100644
index 43cd2c37..00000000
--- a/src/SharpCompress/Buffers/DefaultArrayPool.cs
+++ /dev/null
@@ -1,144 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-#if NETCORE
-using System;
-
-namespace SharpCompress.Buffers
-{
- internal sealed partial class DefaultArrayPool : ArrayPool
- {
- /// The default maximum length of each array in the pool (2^20).
- private const int DefaultMaxArrayLength = 1024 * 1024;
- /// The default maximum number of arrays per bucket that are available for rent.
- private const int DefaultMaxNumberOfArraysPerBucket = 50;
- /// Lazily-allocated empty array used when arrays of length 0 are requested.
- private static T[] s_emptyArray; // we support contracts earlier than those with Array.Empty()
-
- private readonly Bucket[] _buckets;
-
- internal DefaultArrayPool() : this(DefaultMaxArrayLength, DefaultMaxNumberOfArraysPerBucket)
- {
- }
-
- internal DefaultArrayPool(int maxArrayLength, int maxArraysPerBucket)
- {
- if (maxArrayLength <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(maxArrayLength));
- }
- if (maxArraysPerBucket <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(maxArraysPerBucket));
- }
-
- // Our bucketing algorithm has a min length of 2^4 and a max length of 2^30.
- // Constrain the actual max used to those values.
- const int MinimumArrayLength = 0x10, MaximumArrayLength = 0x40000000;
- if (maxArrayLength > MaximumArrayLength)
- {
- maxArrayLength = MaximumArrayLength;
- }
- else if (maxArrayLength < MinimumArrayLength)
- {
- maxArrayLength = MinimumArrayLength;
- }
-
- // Create the buckets.
- int poolId = Id;
- int maxBuckets = Utilities.SelectBucketIndex(maxArrayLength);
- var buckets = new Bucket[maxBuckets + 1];
- for (int i = 0; i < buckets.Length; i++)
- {
- buckets[i] = new Bucket(Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, poolId);
- }
- _buckets = buckets;
- }
-
- /// Gets an ID for the pool to use with events.
- private int Id => GetHashCode();
-
- public override T[] Rent(int minimumLength)
- {
- // Arrays can't be smaller than zero. We allow requesting zero-length arrays (even though
- // pooling such an array isn't valuable) as it's a valid length array, and we want the pool
- // to be usable in general instead of using `new`, even for computed lengths.
- if (minimumLength < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(minimumLength));
- }
- else if (minimumLength == 0)
- {
- // No need for events with the empty array. Our pool is effectively infinite
- // and we'll never allocate for rents and never store for returns.
- return s_emptyArray ?? (s_emptyArray = new T[0]);
- }
-
- T[] buffer = null;
-
- int index = Utilities.SelectBucketIndex(minimumLength);
- if (index < _buckets.Length)
- {
- // Search for an array starting at the 'index' bucket. If the bucket is empty, bump up to the
- // next higher bucket and try that one, but only try at most a few buckets.
- const int MaxBucketsToTry = 2;
- int i = index;
- do
- {
- // Attempt to rent from the bucket. If we get a buffer from it, return it.
- buffer = _buckets[i].Rent();
- if (buffer != null)
- {
- return buffer;
- }
- }
- while (++i < _buckets.Length && i != index + MaxBucketsToTry);
-
- // The pool was exhausted for this buffer size. Allocate a new buffer with a size corresponding
- // to the appropriate bucket.
- buffer = new T[_buckets[index]._bufferLength];
- }
- else
- {
- // The request was for a size too large for the pool. Allocate an array of exactly the requested length.
- // When it's returned to the pool, we'll simply throw it away.
- buffer = new T[minimumLength];
- }
-
- return buffer;
- }
-
- public override void Return(T[] array, bool clearArray = false)
- {
- if (array == null)
- {
- throw new ArgumentNullException(nameof(array));
- }
- else if (array.Length == 0)
- {
- // Ignore empty arrays. When a zero-length array is rented, we return a singleton
- // rather than actually taking a buffer out of the lowest bucket.
- return;
- }
-
- // Determine with what bucket this array length is associated
- int bucket = Utilities.SelectBucketIndex(array.Length);
-
- // If we can tell that the buffer was allocated, drop it. Otherwise, check if we have space in the pool
- if (bucket < _buckets.Length)
- {
- // Clear the array if the user requests
- if (clearArray)
- {
- Array.Clear(array, 0, array.Length);
- }
-
- // Return the buffer to its bucket. In the future, we might consider having Return return false
- // instead of dropping a bucket, in which case we could try to return to a lower-sized bucket,
- // just as how in Rent we allow renting from a higher-sized bucket.
- _buckets[bucket].Return(array);
- }
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/src/SharpCompress/Buffers/DefaultArrayPoolBucket.cs b/src/SharpCompress/Buffers/DefaultArrayPoolBucket.cs
deleted file mode 100644
index 30124889..00000000
--- a/src/SharpCompress/Buffers/DefaultArrayPoolBucket.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#if NETCORE
-using System;
-using System.Diagnostics;
-using System.Threading;
-
-namespace SharpCompress.Buffers
-{
- internal sealed partial class DefaultArrayPool : ArrayPool
- {
- /// Provides a thread-safe bucket containing buffers that can be Rent'd and Return'd.
- private sealed class Bucket
- {
- internal readonly int _bufferLength;
- private readonly T[][] _buffers;
- private readonly int _poolId;
-
- private SpinLock _lock; // do not make this readonly; it's a mutable struct
- private int _index;
-
- ///
- /// Creates the pool with numberOfBuffers arrays where each buffer is of bufferLength length.
- ///
- internal Bucket(int bufferLength, int numberOfBuffers, int poolId)
- {
- _lock = new SpinLock(Debugger.IsAttached); // only enable thread tracking if debugger is attached; it adds non-trivial overheads to Enter/Exit
- _buffers = new T[numberOfBuffers][];
- _bufferLength = bufferLength;
- _poolId = poolId;
- }
-
- /// Gets an ID for the bucket to use with events.
- internal int Id => GetHashCode();
-
- /// Takes an array from the bucket. If the bucket is empty, returns null.
- internal T[] Rent()
- {
- T[][] buffers = _buffers;
- T[] buffer = null;
-
- // While holding the lock, grab whatever is at the next available index and
- // update the index. We do as little work as possible while holding the spin
- // lock to minimize contention with other threads. The try/finally is
- // necessary to properly handle thread aborts on platforms which have them.
- bool lockTaken = false, allocateBuffer = false;
- try
- {
- _lock.Enter(ref lockTaken);
-
- if (_index < buffers.Length)
- {
- buffer = buffers[_index];
- buffers[_index++] = null;
- allocateBuffer = buffer == null;
- }
- }
- finally
- {
- if (lockTaken) _lock.Exit(false);
- }
-
- // While we were holding the lock, we grabbed whatever was at the next available index, if
- // there was one. If we tried and if we got back null, that means we hadn't yet allocated
- // for that slot, in which case we should do so now.
- if (allocateBuffer)
- {
- buffer = new T[_bufferLength];
- }
-
- return buffer;
- }
-
- ///
- /// Attempts to return the buffer to the bucket. If successful, the buffer will be stored
- /// in the bucket and true will be returned; otherwise, the buffer won't be stored, and false
- /// will be returned.
- ///
- internal void Return(T[] array)
- {
- // Check to see if the buffer is the correct size for this bucket
- if (array.Length != _bufferLength)
- {
- throw new ArgumentException("Buffer not from pool", nameof(array));
- }
-
- // While holding the spin lock, if there's room available in the bucket,
- // put the buffer into the next available slot. Otherwise, we just drop it.
- // The try/finally is necessary to properly handle thread aborts on platforms
- // which have them.
- bool lockTaken = false;
- try
- {
- _lock.Enter(ref lockTaken);
-
- if (_index != 0)
- {
- _buffers[--_index] = array;
- }
- }
- finally
- {
- if (lockTaken) _lock.Exit(false);
- }
- }
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/src/SharpCompress/Buffers/Utilities.cs b/src/SharpCompress/Buffers/Utilities.cs
deleted file mode 100644
index f4100e37..00000000
--- a/src/SharpCompress/Buffers/Utilities.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-#if NETCORE
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace SharpCompress.Buffers
-{
- internal static class Utilities
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static int SelectBucketIndex(int bufferSize)
- {
- Debug.Assert(bufferSize > 0);
-
- uint bitsRemaining = ((uint)bufferSize - 1) >> 4;
-
- int poolIndex = 0;
- if (bitsRemaining > 0xFFFF) { bitsRemaining >>= 16; poolIndex = 16; }
- if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; }
- if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; }
- if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; }
- if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; }
-
- return poolIndex + (int)bitsRemaining;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static int GetMaxSizeForBucket(int binIndex)
- {
- int maxSize = 16 << binIndex;
- Debug.Assert(maxSize >= 0);
- return maxSize;
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj
index dfc597e2..ce617455 100644
--- a/src/SharpCompress/SharpCompress.csproj
+++ b/src/SharpCompress/SharpCompress.csproj
@@ -29,11 +29,13 @@
+
$(DefineConstants);NETCORE
+
-
\ No newline at end of file
+
diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs
index e97d093d..d1d45582 100644
--- a/src/SharpCompress/Utility.cs
+++ b/src/SharpCompress/Utility.cs
@@ -1,29 +1,26 @@
using System;
+#if NETCORE
+using System.Buffers;
+#endif
using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.InteropServices;
-#if NETCORE
-using SharpCompress.Buffers;
-#endif
+
using SharpCompress.Readers;
namespace SharpCompress
{
internal static class Utility
{
- public static ReadOnlyCollection ToReadOnly(this IEnumerable items)
+ public static ReadOnlyCollection ToReadOnly(this ICollection items)
{
- return new ReadOnlyCollection(items.ToList());
+ return new ReadOnlyCollection(items);
}
///
/// Performs an unsigned bitwise right shift with the specified number
///
/// Number to operate on
- /// Ammount of bits to shift
+ /// Amount of bits to shift
/// The resulting number from the shift operation
public static int URShift(int number, int bits)
{
@@ -38,7 +35,7 @@ namespace SharpCompress
/// Performs an unsigned bitwise right shift with the specified number
///
/// Number to operate on
- /// Ammount of bits to shift
+ /// Amount of bits to shift
/// The resulting number from the shift operation
public static long URShift(long number, int bits)
{
@@ -81,7 +78,8 @@ namespace SharpCompress
// see https://stackoverflow.com/questions/1897555/what-is-the-equivalent-of-memset-in-c
private static readonly Action MemsetDelegate = CreateMemsetDelegate();
- private static Action CreateMemsetDelegate() {
+ private static Action CreateMemsetDelegate()
+ {
var dynamicMethod = new DynamicMethod(
"Memset",
MethodAttributes.Public | MethodAttributes.Static,
@@ -108,7 +106,7 @@ namespace SharpCompress
#else
public static void Memset(byte[] array, byte what, int length)
{
- for(var i = 0; i < length; i++)
+ for (var i = 0; i < length; i++)
{
array[i] = what;
}
@@ -117,7 +115,7 @@ namespace SharpCompress
public static void Memset(T[] array, T what, int length)
{
- for(var i = 0; i < length; i++)
+ for (var i = 0; i < length; i++)
{
array[i] = what;
}
@@ -184,7 +182,7 @@ namespace SharpCompress
action(item);
}
}
-
+
public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
{
if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue)
@@ -440,4 +438,4 @@ namespace SharpCompress
return true;
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj
index 813fcee4..6f798583 100644
--- a/tests/SharpCompress.Test/SharpCompress.Test.csproj
+++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj
@@ -18,4 +18,4 @@
-
\ No newline at end of file
+