mirror of
https://github.com/aaru-dps/AaruBenchmark.git
synced 2025-12-16 19:24:36 +00:00
Add native Fletcher-32.
This commit is contained in:
@@ -44,22 +44,30 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Implements the Fletcher-32 algorithm</summary>
|
||||
public sealed class Fletcher32Context : IChecksum
|
||||
{
|
||||
const ushort FLETCHER_MODULE = 0xFFFF;
|
||||
const uint NMAX = 5552;
|
||||
ushort _sum1, _sum2;
|
||||
const ushort FLETCHER_MODULE = 0xFFFF;
|
||||
const uint NMAX = 5552;
|
||||
readonly IntPtr _nativeContext;
|
||||
ushort _sum1, _sum2;
|
||||
readonly bool _useNative;
|
||||
|
||||
/// <summary>Initializes the Fletcher-32 sums</summary>
|
||||
public Fletcher32Context()
|
||||
{
|
||||
_sum1 = 0xFFFF;
|
||||
_sum2 = 0xFFFF;
|
||||
|
||||
if(!Native.IsSupported)
|
||||
return;
|
||||
|
||||
_nativeContext = fletcher32_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len);
|
||||
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len, _useNative, _nativeContext);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
@@ -72,6 +80,12 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
if(!_useNative)
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
fletcher32_final(_nativeContext, ref finalSum);
|
||||
fletcher32_free(_nativeContext);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
@@ -79,8 +93,15 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var fletcherOutput = new StringBuilder();
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
if(_useNative)
|
||||
{
|
||||
fletcher32_final(_nativeContext, ref finalSum);
|
||||
fletcher32_free(_nativeContext);
|
||||
}
|
||||
|
||||
var fletcherOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
@@ -88,8 +109,28 @@ namespace Aaru6.Checksums
|
||||
return fletcherOutput.ToString();
|
||||
}
|
||||
|
||||
static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len)
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr fletcher32_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int fletcher32_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int fletcher32_final(IntPtr ctx, ref uint crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void fletcher32_free(IntPtr ctx);
|
||||
|
||||
static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len, bool useNative,
|
||||
IntPtr nativeContext)
|
||||
{
|
||||
if(useNative)
|
||||
{
|
||||
fletcher32_update(nativeContext, data, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint sum1 = previousSum1;
|
||||
uint sum2 = previousSum2;
|
||||
uint n;
|
||||
@@ -253,6 +294,17 @@ namespace Aaru6.Checksums
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash)
|
||||
{
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative)
|
||||
{
|
||||
nativeContext = fletcher32_init();
|
||||
|
||||
if(nativeContext == IntPtr.Zero)
|
||||
useNative = false;
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
ushort localSum1 = 0xFFFF;
|
||||
@@ -263,13 +315,19 @@ namespace Aaru6.Checksums
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
Step(ref localSum1, ref localSum2, buffer, (uint)read);
|
||||
Step(ref localSum1, ref localSum2, buffer, (uint)read, useNative, nativeContext);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
|
||||
if(useNative)
|
||||
{
|
||||
fletcher32_final(nativeContext, ref finalSum);
|
||||
fletcher32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
var fletcherOutput = new StringBuilder();
|
||||
@@ -288,13 +346,30 @@ namespace Aaru6.Checksums
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash)
|
||||
{
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative)
|
||||
{
|
||||
nativeContext = fletcher32_init();
|
||||
|
||||
if(nativeContext == IntPtr.Zero)
|
||||
useNative = false;
|
||||
}
|
||||
|
||||
ushort localSum1 = 0xFFFF;
|
||||
ushort localSum2 = 0xFFFF;
|
||||
|
||||
Step(ref localSum1, ref localSum2, data, len);
|
||||
Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext);
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
|
||||
if(useNative)
|
||||
{
|
||||
fletcher32_final(nativeContext, ref finalSum);
|
||||
fletcher32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
var adlerOutput = new StringBuilder();
|
||||
@@ -319,8 +394,8 @@ namespace Aaru6.Checksums
|
||||
const byte NMAX = 22;
|
||||
|
||||
readonly IntPtr _nativeContext;
|
||||
byte _sum1, _sum2;
|
||||
readonly bool _useNative;
|
||||
byte _sum1, _sum2;
|
||||
|
||||
/// <summary>Initializes the Fletcher-16 sums</summary>
|
||||
public Fletcher16Context()
|
||||
|
||||
@@ -99,6 +99,8 @@ namespace AaruBenchmark.Checksums
|
||||
|
||||
public static void Fletcher32()
|
||||
{
|
||||
Native.ForceManaged = true;
|
||||
|
||||
byte[] data = new byte[1048576];
|
||||
|
||||
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
||||
|
||||
@@ -76,18 +76,6 @@ namespace AaruBenchmark.Checksums
|
||||
0xb5, 0xf2, 0x8c, 0xbb, 0x4a, 0xa5, 0x1b, 0x40, 0x7c, 0xb6
|
||||
};
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr fletcher32_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int fletcher32_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int fletcher32_final(IntPtr ctx, ref uint crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void fletcher32_free(IntPtr ctx);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr spamsum_init();
|
||||
|
||||
@@ -124,39 +112,23 @@ namespace AaruBenchmark.Checksums
|
||||
|
||||
public static void Fletcher32()
|
||||
{
|
||||
byte[] data = new byte[1048576];
|
||||
uint fletcher32 = 0;
|
||||
byte[] hash;
|
||||
Native.ForceManaged = false;
|
||||
|
||||
byte[] data = new byte[1048576];
|
||||
|
||||
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
||||
|
||||
fs.Read(data, 0, 1048576);
|
||||
fs.Close();
|
||||
fs.Dispose();
|
||||
IChecksum ctx = new Fletcher32Context();
|
||||
ctx.Update(data);
|
||||
byte[] result = ctx.Final();
|
||||
|
||||
IntPtr ctx = fletcher32_init();
|
||||
if(result?.Length != _expectedRandomFletcher32.Length)
|
||||
throw new Exception("Invalid hash length");
|
||||
|
||||
if(ctx == IntPtr.Zero)
|
||||
throw new Exception("Could not initialize digest");
|
||||
|
||||
int ret = fletcher32_update(ctx, data, (uint)data.Length);
|
||||
|
||||
if(ret != 0)
|
||||
throw new Exception("Could not digest block");
|
||||
|
||||
ret = fletcher32_final(ctx, ref fletcher32);
|
||||
|
||||
if(ret != 0)
|
||||
throw new Exception("Could not finalize hash");
|
||||
|
||||
fletcher32_free(ctx);
|
||||
|
||||
fletcher32 = ((fletcher32 << 8) & 0xFF00FF00) | ((fletcher32 >> 8) & 0xFF00FF);
|
||||
fletcher32 = (fletcher32 << 16) | (fletcher32 >> 16);
|
||||
|
||||
hash = BitConverter.GetBytes(fletcher32);
|
||||
|
||||
if(hash.Where((t, i) => t != _expectedRandomFletcher32[i]).Any())
|
||||
if(result.Where((t, i) => t != _expectedRandomFletcher32[i]).Any())
|
||||
throw new Exception("Invalid hash value");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user