Clean up SHA1
This commit is contained in:
parent
4566b744d9
commit
9a0403617b
|
@ -7,40 +7,6 @@ using BizHawk.Common.BufferExtensions;
|
|||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public interface ISHA1
|
||||
{
|
||||
byte[] ComputeHash(byte[] buffer);
|
||||
}
|
||||
|
||||
public sealed class NETSHA1 : ISHA1
|
||||
{
|
||||
private readonly SHA1 _sha1Impl;
|
||||
|
||||
public NETSHA1()
|
||||
{
|
||||
_sha1Impl = SHA1.Create();
|
||||
Debug.Assert(_sha1Impl.CanReuseTransform && _sha1Impl.HashSize is SHA1Checksum.EXPECTED_LENGTH);
|
||||
}
|
||||
|
||||
public byte[] ComputeHash(byte[] buffer)
|
||||
=> _sha1Impl.ComputeHash(buffer);
|
||||
}
|
||||
|
||||
public sealed class FastSHA1 : ISHA1
|
||||
{
|
||||
public unsafe byte[] ComputeHash(byte[] buffer)
|
||||
{
|
||||
// Set SHA1 start state
|
||||
var state = stackalloc uint[] { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
|
||||
// This will use dedicated SHA instructions, which perform 4x faster than a generic implementation
|
||||
LibBizHash.BizCalcSha1((IntPtr)state, buffer, buffer.Length);
|
||||
// The copy seems wasteful, but pinning the state down actually has a bigger performance impact
|
||||
var ret = new byte[20];
|
||||
Marshal.Copy((IntPtr)state, ret, 0, 20);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>uses <see cref="SHA1"/> implementation from BCL</summary>
|
||||
/// <seealso cref="CRC32Checksum"/>
|
||||
/// <seealso cref="MD5Checksum"/>
|
||||
|
@ -70,27 +36,49 @@ namespace BizHawk.Common
|
|||
return impl.GetHashAndReset();
|
||||
}
|
||||
#else
|
||||
private static ISHA1? _sha1Impl;
|
||||
private static unsafe byte[] UnmanagedImpl(byte[] buffer)
|
||||
{
|
||||
// Set SHA1 start state
|
||||
var state = stackalloc uint[] { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
|
||||
// This will use dedicated SHA instructions, which perform 4x faster than a generic implementation
|
||||
LibBizHash.BizCalcSha1((IntPtr) state, buffer, buffer.Length);
|
||||
// The copy seems wasteful, but pinning the state down actually has a bigger performance impact
|
||||
var ret = new byte[20];
|
||||
Marshal.Copy((IntPtr) state, ret, 0, 20);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static ISHA1 SHA1Impl
|
||||
private static SHA1? _sha1Impl;
|
||||
|
||||
private static SHA1 SHA1Impl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sha1Impl == null)
|
||||
{
|
||||
_sha1Impl = LibBizHash.BizSupportsShaInstructions()
|
||||
? new FastSHA1()
|
||||
: new NETSHA1();
|
||||
_sha1Impl = SHA1.Create();
|
||||
Debug.Assert(_sha1Impl.CanReuseTransform && _sha1Impl.HashSize is EXPECTED_LENGTH);
|
||||
}
|
||||
return _sha1Impl;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Compute(byte[] data)
|
||||
=> SHA1Impl.ComputeHash(data);
|
||||
=> LibBizHash.BizSupportsShaInstructions()
|
||||
? UnmanagedImpl(data)
|
||||
: SHA1Impl.ComputeHash(data);
|
||||
|
||||
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);
|
||||
}
|
||||
using var impl = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
|
||||
impl.AppendData(dataA);
|
||||
impl.AppendData(dataB);
|
||||
|
|
Loading…
Reference in New Issue