From 64a2c9f9fb23ebf9b61eb4e62f8ccf3782f5bda2 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 14 Oct 2021 00:11:16 +0100 Subject: [PATCH] Add native Fletcher-16. --- Aaru6.Checksums/FletcherContext.cs | 92 +++++++++++++++++++++++++-- AaruBenchmark/Checksums/Aaru.cs | 10 +-- AaruBenchmark/Checksums/Aaru6.cs | 2 + AaruBenchmark/Checksums/AaruNative.cs | 45 +++---------- 4 files changed, 101 insertions(+), 48 deletions(-) diff --git a/Aaru6.Checksums/FletcherContext.cs b/Aaru6.Checksums/FletcherContext.cs index 1376214..f0a26f8 100644 --- a/Aaru6.Checksums/FletcherContext.cs +++ b/Aaru6.Checksums/FletcherContext.cs @@ -32,7 +32,9 @@ // Disabled because the speed is abnormally slow +using System; using System.IO; +using System.Runtime.InteropServices; using System.Text; using Aaru.CommonTypes.Interfaces; using Aaru.Helpers; @@ -315,20 +317,29 @@ namespace Aaru6.Checksums { const byte FLETCHER_MODULE = 0xFF; const byte NMAX = 22; - byte _sum1, _sum2; + + readonly IntPtr _nativeContext; + byte _sum1, _sum2; + readonly bool _useNative; /// Initializes the Fletcher-16 sums public Fletcher16Context() { _sum1 = 0xFF; _sum2 = 0xFF; + + if(!Native.IsSupported) + return; + + _nativeContext = fletcher16_init(); + _useNative = _nativeContext != IntPtr.Zero; } /// /// Updates the hash with data. /// Data buffer. /// Length of buffer to hash. - 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); /// /// Updates the hash with data. @@ -341,6 +352,12 @@ namespace Aaru6.Checksums { ushort finalSum = (ushort)((_sum2 << 8) | _sum1); + if(!_useNative) + return BigEndianBitConverter.GetBytes(finalSum); + + fletcher16_final(_nativeContext, ref finalSum); + fletcher16_free(_nativeContext); + return BigEndianBitConverter.GetBytes(finalSum); } @@ -348,8 +365,15 @@ namespace Aaru6.Checksums /// Returns a hexadecimal representation of the hash value. public string End() { - ushort finalSum = (ushort)((_sum2 << 8) | _sum1); - var fletcherOutput = new StringBuilder(); + ushort finalSum = (ushort)((_sum2 << 8) | _sum1); + + if(_useNative) + { + fletcher16_final(_nativeContext, ref finalSum); + fletcher16_free(_nativeContext); + } + + var fletcherOutput = new StringBuilder(); for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); @@ -357,8 +381,28 @@ namespace Aaru6.Checksums return fletcherOutput.ToString(); } - static void Step(ref byte previousSum1, ref byte previousSum2, byte[] data, uint len) + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern IntPtr fletcher16_init(); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern int fletcher16_update(IntPtr ctx, byte[] data, uint len); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern int fletcher16_final(IntPtr ctx, ref ushort checksum); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern void fletcher16_free(IntPtr ctx); + + static void Step(ref byte previousSum1, ref byte previousSum2, byte[] data, uint len, bool useNative, + IntPtr nativeContext) { + if(useNative) + { + fletcher16_update(nativeContext, data, len); + + return; + } + uint sum1 = previousSum1; uint sum2 = previousSum2; uint n; @@ -502,6 +546,17 @@ namespace Aaru6.Checksums /// Byte array of the hash value. public static string File(string filename, out byte[] hash) { + bool useNative = Native.IsSupported; + IntPtr nativeContext = IntPtr.Zero; + + if(useNative) + { + nativeContext = fletcher16_init(); + + if(nativeContext == IntPtr.Zero) + useNative = false; + } + var fileStream = new FileStream(filename, FileMode.Open); byte localSum1 = 0xFF; @@ -512,13 +567,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); } ushort finalSum = (ushort)((localSum2 << 8) | localSum1); + if(useNative) + { + fletcher16_final(nativeContext, ref finalSum); + fletcher16_free(nativeContext); + } + hash = BigEndianBitConverter.GetBytes(finalSum); var fletcherOutput = new StringBuilder(); @@ -537,13 +598,30 @@ namespace Aaru6.Checksums /// Byte array of the hash value. public static string Data(byte[] data, uint len, out byte[] hash) { + bool useNative = Native.IsSupported; + IntPtr nativeContext = IntPtr.Zero; + + if(useNative) + { + nativeContext = fletcher16_init(); + + if(nativeContext == IntPtr.Zero) + useNative = false; + } + byte localSum1 = 0xFF; byte localSum2 = 0xFF; - Step(ref localSum1, ref localSum2, data, len); + Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext); ushort finalSum = (ushort)((localSum2 << 8) | localSum1); + if(useNative) + { + fletcher16_final(nativeContext, ref finalSum); + fletcher16_free(nativeContext); + } + hash = BigEndianBitConverter.GetBytes(finalSum); var adlerOutput = new StringBuilder(); diff --git a/AaruBenchmark/Checksums/Aaru.cs b/AaruBenchmark/Checksums/Aaru.cs index c6fded4..7a37adb 100644 --- a/AaruBenchmark/Checksums/Aaru.cs +++ b/AaruBenchmark/Checksums/Aaru.cs @@ -148,12 +148,12 @@ namespace AaruBenchmark.Checksums IChecksum ctx = new CRC16CCITTContext(); ctx.Update(data); byte[] result = ctx.Final(); - /* - if(result?.Length != _expectedRandomCrc16Ccitt.Length) - throw new Exception("Invalid hash length"); - if(result.Where((t, i) => t != _expectedRandomCrc16Ccitt[i]).Any()) - throw new Exception("Invalid hash value");*/ + if(result?.Length != _expectedRandomCrc16Ccitt.Length) + throw new Exception("Invalid hash length"); + + if(result.Where((t, i) => t != _expectedRandomCrc16Ccitt[i]).Any()) + throw new Exception("Invalid hash value"); } public static void Crc16() diff --git a/AaruBenchmark/Checksums/Aaru6.cs b/AaruBenchmark/Checksums/Aaru6.cs index d0d2563..7a40034 100644 --- a/AaruBenchmark/Checksums/Aaru6.cs +++ b/AaruBenchmark/Checksums/Aaru6.cs @@ -77,6 +77,8 @@ namespace AaruBenchmark.Checksums public static void Fletcher16() { + Native.ForceManaged = true; + byte[] data = new byte[1048576]; var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read); diff --git a/AaruBenchmark/Checksums/AaruNative.cs b/AaruBenchmark/Checksums/AaruNative.cs index 663fa8a..c4a8f42 100644 --- a/AaruBenchmark/Checksums/AaruNative.cs +++ b/AaruBenchmark/Checksums/AaruNative.cs @@ -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 fletcher16_init(); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern int fletcher16_update(IntPtr ctx, byte[] data, uint len); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern int fletcher16_final(IntPtr ctx, ref ushort crc); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern void fletcher16_free(IntPtr ctx); - [DllImport("libAaru.Checksums.Native", SetLastError = true)] static extern IntPtr fletcher32_init(); @@ -114,38 +102,23 @@ namespace AaruBenchmark.Checksums public static void Fletcher16() { - byte[] data = new byte[1048576]; - ushort fletcher16 = 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 Fletcher16Context(); + ctx.Update(data); + byte[] result = ctx.Final(); - IntPtr ctx = fletcher16_init(); + if(result?.Length != _expectedRandomFletcher16.Length) + throw new Exception("Invalid hash length"); - if(ctx == IntPtr.Zero) - throw new Exception("Could not initialize digest"); - - int ret = fletcher16_update(ctx, data, (uint)data.Length); - - if(ret != 0) - throw new Exception("Could not digest block"); - - ret = fletcher16_final(ctx, ref fletcher16); - - if(ret != 0) - throw new Exception("Could not finalize hash"); - - fletcher16_free(ctx); - - fletcher16 = (ushort)((fletcher16 << 8) | (fletcher16 >> 8)); - - hash = BitConverter.GetBytes(fletcher16); - - if(hash.Where((t, i) => t != _expectedRandomFletcher16[i]).Any()) + if(result.Where((t, i) => t != _expectedRandomFletcher16[i]).Any()) throw new Exception("Invalid hash value"); }