From b8182f914990ab084c4c2246c8865508414cb22b Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 26 Nov 2022 18:36:58 +1000 Subject: [PATCH] Extract `ConcatArray` helper --- .../Extensions/CollectionExtensions.cs | 28 +++++++++++++++++++ src/BizHawk.Common/checksums/SHA1Checksum.cs | 11 ++------ .../CollectionExtensionTests.cs | 12 ++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/BizHawk.Common/Extensions/CollectionExtensions.cs b/src/BizHawk.Common/Extensions/CollectionExtensions.cs index f2d6915239..4c03641450 100644 --- a/src/BizHawk.Common/Extensions/CollectionExtensions.cs +++ b/src/BizHawk.Common/Extensions/CollectionExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -122,6 +123,33 @@ namespace BizHawk.Common.CollectionExtensions foreach (var item in collection) list.Add(item); } + /// + /// portion of that was written to, + /// unless either span is empty, in which case the other reference is returned
+ /// if is too small, returns + ///
+ public static ReadOnlySpan ConcatArray(this ReadOnlySpan a, ReadOnlySpan b, Span dest) + { + if (b.Length is 0) return a; + if (a.Length is 0) return b; + var combinedLen = a.Length + b.Length; + if (combinedLen < dest.Length) return Span.Empty; + a.CopyTo(dest); + b.CopyTo(dest.Slice(start: a.Length)); + return dest.Slice(start: 0, length: combinedLen); + } + + /// freshly-allocated array, unless either array is empty, in which case the other reference is returned + public static T[] ConcatArray(this T[] a, T[] b) + { + if (b.Length is 0) return a; + if (a.Length is 0) return b; + var combined = new T[a.Length + b.Length]; + var returned = ((ReadOnlySpan) a).ConcatArray(b, combined); + Debug.Assert(returned == combined); + return combined; + } + public static bool CountIsAtLeast(this IEnumerable collection, int n) => collection is ICollection countable ? countable.Count >= n diff --git a/src/BizHawk.Common/checksums/SHA1Checksum.cs b/src/BizHawk.Common/checksums/SHA1Checksum.cs index ba14e9a45c..a4013bb6ca 100644 --- a/src/BizHawk.Common/checksums/SHA1Checksum.cs +++ b/src/BizHawk.Common/checksums/SHA1Checksum.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using System.Security.Cryptography; using BizHawk.Common.BufferExtensions; +using BizHawk.Common.CollectionExtensions; namespace BizHawk.Common { @@ -70,15 +71,7 @@ namespace BizHawk.Common public static byte[] ComputeConcat(byte[] dataA, byte[] dataB) { - if (LibBizHash.BizSupportsShaInstructions()) - { - var concat = new byte[dataA.Length + dataB.Length]; - Array.Copy(sourceArray: dataA, destinationArray: concat, length: dataA.Length); - Array.Copy( - sourceArray: dataB, sourceIndex: 0, - destinationArray: concat, destinationIndex: dataA.Length, length: dataB.Length); - return UnmanagedImpl(concat); - } + if (LibBizHash.BizSupportsShaInstructions()) return UnmanagedImpl(dataA.ConcatArray(dataB)); using var impl = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); impl.AppendData(dataA); impl.AppendData(dataB); diff --git a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs index d545ab2e89..620a6fe1d8 100644 --- a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs +++ b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using BizHawk.Common.CollectionExtensions; @@ -63,6 +64,17 @@ namespace BizHawk.Tests.Common.CollectionExtensions Assert.AreEqual(4, b.Count, nameof(CE.AddRange) + " failed on (ICollection not List)"); } + [TestMethod] + public void TestConcatArray() + { + var a123 = new[] { 1, 2, 3 }; + var a456 = new[] { 4, 5, 6 }; + Assert.IsTrue(a123.ConcatArray(a456).SequenceEqual(new[] { 1, 2, 3, 4, 5, 6 })); + Assert.AreSame(a123, a123.ConcatArray(Array.Empty())); + Assert.AreSame(a456, Array.Empty().ConcatArray(a456)); + Assert.AreEqual(0, Array.Empty().ConcatArray(Array.Empty()).Length); + } + [TestMethod] public void TestRemoveAll() {