mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add native checksums.
This commit is contained in:
@@ -65,6 +65,7 @@
|
||||
<Compile Include="CRC32\arm_simd.cs" />
|
||||
<Compile Include="CRC32\clmul.cs" />
|
||||
<Compile Include="CRC64\clmul.cs" />
|
||||
<Compile Include="Native.cs" />
|
||||
<Compile Include="Register.cs" />
|
||||
<Compile Include="SpamSumContext.cs" />
|
||||
<Compile Include="Adler32Context.cs" />
|
||||
@@ -100,6 +101,7 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aaru.Checksums.Native" Version="6.0.0-alpha6" />
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.1" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
// Copyright (C) Jean-loup Gailly
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Text;
|
||||
using Aaru.Checksums.Adler32;
|
||||
@@ -52,6 +54,8 @@ namespace Aaru.Checksums
|
||||
{
|
||||
internal const ushort ADLER_MODULE = 65521;
|
||||
internal const uint NMAX = 5552;
|
||||
readonly IntPtr _nativeContext;
|
||||
readonly bool _useNative;
|
||||
ushort _sum1, _sum2;
|
||||
|
||||
/// <summary>Initializes the Adler-32 sums</summary>
|
||||
@@ -59,13 +63,19 @@ namespace Aaru.Checksums
|
||||
{
|
||||
_sum1 = 1;
|
||||
_sum2 = 0;
|
||||
|
||||
if(!Native.IsSupported)
|
||||
return;
|
||||
|
||||
_nativeContext = adler32_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>
|
||||
@@ -78,6 +88,12 @@ namespace Aaru.Checksums
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
if(!_useNative)
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
adler32_final(_nativeContext, ref finalSum);
|
||||
adler32_free(_nativeContext);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
@@ -85,8 +101,15 @@ namespace Aaru.Checksums
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var adlerOutput = new StringBuilder();
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
if(_useNative)
|
||||
{
|
||||
adler32_final(_nativeContext, ref finalSum);
|
||||
adler32_free(_nativeContext);
|
||||
}
|
||||
|
||||
var adlerOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
@@ -94,8 +117,28 @@ namespace Aaru.Checksums
|
||||
return adlerOutput.ToString();
|
||||
}
|
||||
|
||||
static void Step(ref ushort preSum1, ref ushort preSum2, byte[] data, uint len)
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr adler32_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int adler32_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int adler32_final(IntPtr ctx, ref uint checksum);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void adler32_free(IntPtr ctx);
|
||||
|
||||
static void Step(ref ushort preSum1, ref ushort preSum2, byte[] data, uint len, bool useNative,
|
||||
IntPtr nativeContext)
|
||||
{
|
||||
if(useNative)
|
||||
{
|
||||
adler32_update(nativeContext, data, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(Ssse3.IsSupported)
|
||||
{
|
||||
Adler32.Ssse3.Step(ref preSum1, ref preSum2, data, len);
|
||||
@@ -273,6 +316,17 @@ namespace Aaru.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 = adler32_init();
|
||||
|
||||
if(nativeContext == IntPtr.Zero)
|
||||
useNative = false;
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
ushort localSum1 = 1;
|
||||
@@ -283,12 +337,18 @@ namespace Aaru.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)
|
||||
{
|
||||
adler32_final(nativeContext, ref finalSum);
|
||||
adler32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
var adlerOutput = new StringBuilder();
|
||||
@@ -307,13 +367,30 @@ namespace Aaru.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 = adler32_init();
|
||||
|
||||
if(nativeContext == IntPtr.Zero)
|
||||
useNative = false;
|
||||
}
|
||||
|
||||
ushort localSum1 = 1;
|
||||
ushort localSum2 = 0;
|
||||
|
||||
Step(ref localSum1, ref localSum2, data, len);
|
||||
Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext);
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
|
||||
if(useNative)
|
||||
{
|
||||
adler32_final(nativeContext, ref finalSum);
|
||||
adler32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(finalSum);
|
||||
|
||||
var adlerOutput = new StringBuilder();
|
||||
|
||||
345
CRC16Context.cs
345
CRC16Context.cs
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
@@ -44,7 +45,11 @@ namespace Aaru.Checksums
|
||||
{
|
||||
readonly ushort _finalSeed;
|
||||
readonly bool _inverse;
|
||||
readonly IntPtr _nativeContext;
|
||||
readonly ushort[][] _table;
|
||||
readonly bool _useCcitt;
|
||||
readonly bool _useIbm;
|
||||
readonly bool _useNative;
|
||||
ushort _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
@@ -54,7 +59,29 @@ namespace Aaru.Checksums
|
||||
_finalSeed = seed;
|
||||
_inverse = inverse;
|
||||
|
||||
_table = table ?? GenerateTable(polynomial, inverse);
|
||||
_useNative = Native.IsSupported;
|
||||
|
||||
_useCcitt = polynomial == CRC16CCITTContext.CRC16_CCITT_POLY &&
|
||||
seed == CRC16CCITTContext.CRC16_CCITT_SEED && inverse;
|
||||
|
||||
_useIbm = polynomial == CRC16IBMContext.CRC16_IBM_POLY && seed == CRC16IBMContext.CRC16_IBM_SEED &&
|
||||
!inverse;
|
||||
|
||||
if(_useCcitt && _useNative)
|
||||
{
|
||||
_nativeContext = crc16_ccitt_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
else if(_useIbm && _useNative)
|
||||
{
|
||||
_nativeContext = crc16_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
_useNative = false;
|
||||
|
||||
if(!_useNative)
|
||||
_table = table ?? GenerateTable(polynomial, inverse);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -63,10 +90,26 @@ namespace Aaru.Checksums
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
if(_inverse)
|
||||
StepInverse(ref _hashInt, _table, data, len);
|
||||
else
|
||||
Step(ref _hashInt, _table, data, len);
|
||||
switch(_useNative)
|
||||
{
|
||||
case true when _useCcitt:
|
||||
crc16_ccitt_update(_nativeContext, data, len);
|
||||
|
||||
break;
|
||||
case true when _useIbm:
|
||||
crc16_update(_nativeContext, data, len);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(_inverse)
|
||||
StepInverse(ref _hashInt, _table, data, len);
|
||||
else
|
||||
Step(ref _hashInt, _table, data, len);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -76,19 +119,65 @@ namespace Aaru.Checksums
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => !_inverse ? BigEndianBitConverter.GetBytes((ushort)(_hashInt ^ _finalSeed))
|
||||
: BigEndianBitConverter.GetBytes((ushort)~(_hashInt ^ _finalSeed));
|
||||
public byte[] Final()
|
||||
{
|
||||
ushort crc = 0;
|
||||
|
||||
switch(_useNative)
|
||||
{
|
||||
case true when _useCcitt:
|
||||
crc16_ccitt_final(_nativeContext, ref crc);
|
||||
crc16_ccitt_free(_nativeContext);
|
||||
|
||||
break;
|
||||
case true when _useIbm:
|
||||
crc16_final(_nativeContext, ref crc);
|
||||
crc16_free(_nativeContext);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(_inverse)
|
||||
crc = (ushort)~(_hashInt ^ _finalSeed);
|
||||
else
|
||||
crc = (ushort)(_hashInt ^ _finalSeed);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return BigEndianBitConverter.GetBytes(crc);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
var crc16Output = new StringBuilder();
|
||||
var crc16Output = new StringBuilder();
|
||||
ushort final = 0;
|
||||
|
||||
ushort final = (ushort)(_hashInt ^ _finalSeed);
|
||||
switch(_useNative)
|
||||
{
|
||||
case true when _useCcitt:
|
||||
crc16_ccitt_final(_nativeContext, ref final);
|
||||
crc16_ccitt_free(_nativeContext);
|
||||
|
||||
if(_inverse)
|
||||
final = (ushort)~final;
|
||||
break;
|
||||
case true when _useIbm:
|
||||
crc16_final(_nativeContext, ref final);
|
||||
crc16_free(_nativeContext);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(_inverse)
|
||||
final = (ushort)~(_hashInt ^ _finalSeed);
|
||||
else
|
||||
final = (ushort)(_hashInt ^ _finalSeed);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] finalBytes = BigEndianBitConverter.GetBytes(final);
|
||||
|
||||
@@ -98,6 +187,30 @@ namespace Aaru.Checksums
|
||||
return crc16Output.ToString();
|
||||
}
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr crc16_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc16_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc16_final(IntPtr ctx, ref ushort crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void crc16_free(IntPtr ctx);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr crc16_ccitt_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc16_ccitt_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc16_ccitt_final(IntPtr ctx, ref ushort crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void crc16_ccitt_free(IntPtr ctx);
|
||||
|
||||
static void Step(ref ushort previousCrc, ushort[][] table, byte[] data, uint len)
|
||||
{
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
@@ -234,10 +347,34 @@ namespace Aaru.Checksums
|
||||
public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[][] table,
|
||||
bool inverse)
|
||||
{
|
||||
bool useNative = Native.IsSupported;
|
||||
|
||||
bool useCcitt = polynomial == CRC16CCITTContext.CRC16_CCITT_POLY &&
|
||||
seed == CRC16CCITTContext.CRC16_CCITT_SEED && inverse;
|
||||
|
||||
bool useIbm = polynomial == CRC16IBMContext.CRC16_IBM_POLY && seed == CRC16IBMContext.CRC16_IBM_SEED &&
|
||||
!inverse;
|
||||
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
ushort localHashInt = seed;
|
||||
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
nativeContext = crc16_ccitt_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
nativeContext = crc16_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
byte[] buffer = new byte[65536];
|
||||
@@ -245,18 +382,52 @@ namespace Aaru.Checksums
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)read);
|
||||
else
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read);
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_update(nativeContext, buffer, (uint)read);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_update(nativeContext, buffer, (uint)read);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)read);
|
||||
else
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_final(nativeContext, ref localHashInt);
|
||||
crc16_ccitt_free(nativeContext);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_final(nativeContext, ref localHashInt);
|
||||
crc16_free(nativeContext);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
@@ -281,19 +452,77 @@ namespace Aaru.Checksums
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, ushort polynomial, ushort seed,
|
||||
ushort[][] table, bool inverse)
|
||||
{
|
||||
bool useNative = Native.IsSupported;
|
||||
|
||||
bool useCcitt = polynomial == CRC16CCITTContext.CRC16_CCITT_POLY &&
|
||||
seed == CRC16CCITTContext.CRC16_CCITT_SEED && inverse;
|
||||
|
||||
bool useIbm = polynomial == CRC16IBMContext.CRC16_IBM_POLY && seed == CRC16IBMContext.CRC16_IBM_SEED &&
|
||||
!inverse;
|
||||
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
ushort localHashInt = seed;
|
||||
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
nativeContext = crc16_ccitt_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
nativeContext = crc16_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, data, len);
|
||||
else
|
||||
Step(ref localHashInt, localTable, data, len);
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_update(nativeContext, data, len);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_update(nativeContext, data, len);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, data, len);
|
||||
else
|
||||
Step(ref localHashInt, localTable, data, len);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_final(nativeContext, ref localHashInt);
|
||||
crc16_ccitt_free(nativeContext);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_final(nativeContext, ref localHashInt);
|
||||
crc16_free(nativeContext);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
@@ -314,19 +543,77 @@ namespace Aaru.Checksums
|
||||
/// <returns>CRC16</returns>
|
||||
public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[][] table, bool inverse)
|
||||
{
|
||||
bool useNative = Native.IsSupported;
|
||||
|
||||
bool useCcitt = polynomial == CRC16CCITTContext.CRC16_CCITT_POLY &&
|
||||
seed == CRC16CCITTContext.CRC16_CCITT_SEED && inverse;
|
||||
|
||||
bool useIbm = polynomial == CRC16IBMContext.CRC16_IBM_POLY && seed == CRC16IBMContext.CRC16_IBM_SEED &&
|
||||
!inverse;
|
||||
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
ushort localHashInt = seed;
|
||||
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
nativeContext = crc16_ccitt_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
nativeContext = crc16_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
else
|
||||
Step(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_update(nativeContext, buffer, (uint)buffer.Length);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_update(nativeContext, buffer, (uint)buffer.Length);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
else
|
||||
Step(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
switch(useNative)
|
||||
{
|
||||
case true when useCcitt:
|
||||
crc16_ccitt_final(nativeContext, ref localHashInt);
|
||||
crc16_ccitt_free(nativeContext);
|
||||
|
||||
break;
|
||||
case true when useIbm:
|
||||
crc16_final(nativeContext, ref localHashInt);
|
||||
crc16_free(nativeContext);
|
||||
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return localHashInt;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Aaru.Checksums
|
||||
/// <summary>Implements the CRC16 algorithm with IBM polynomial and seed</summary>
|
||||
public sealed class CRC16IBMContext : Crc16Context
|
||||
{
|
||||
const ushort CRC16_IBM_POLY = 0xA001;
|
||||
const ushort CRC16_IBM_SEED = 0x0000;
|
||||
internal const ushort CRC16_IBM_POLY = 0xA001;
|
||||
internal const ushort CRC16_IBM_SEED = 0x0000;
|
||||
|
||||
static readonly ushort[][] _ibmCrc16Table =
|
||||
{
|
||||
|
||||
113
CRC32Context.cs
113
CRC32Context.cs
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System.Text;
|
||||
@@ -333,8 +334,10 @@ namespace Aaru.Checksums
|
||||
};
|
||||
|
||||
readonly uint _finalSeed;
|
||||
readonly IntPtr _nativeContext;
|
||||
readonly uint[][] _table;
|
||||
readonly bool _useIso;
|
||||
readonly bool _useNative;
|
||||
uint _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
|
||||
@@ -344,6 +347,12 @@ namespace Aaru.Checksums
|
||||
_finalSeed = CRC32_ISO_SEED;
|
||||
_table = _isoCrc32Table;
|
||||
_useIso = true;
|
||||
|
||||
if(!Native.IsSupported)
|
||||
return;
|
||||
|
||||
_nativeContext = crc32_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
|
||||
@@ -353,14 +362,21 @@ namespace Aaru.Checksums
|
||||
_finalSeed = seed;
|
||||
_useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
|
||||
|
||||
_table = GenerateTable(polynomial);
|
||||
if(Native.IsSupported && _useIso)
|
||||
{
|
||||
_nativeContext = crc32_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
_table = GenerateTable(polynomial);
|
||||
}
|
||||
|
||||
/// <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 _hashInt, _table, data, len, _useIso);
|
||||
public void Update(byte[] data, uint len) =>
|
||||
Step(ref _hashInt, _table, data, len, _useIso, _useNative, _nativeContext);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
@@ -369,20 +385,52 @@ namespace Aaru.Checksums
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed);
|
||||
public byte[] Final()
|
||||
{
|
||||
uint crc = _hashInt ^ _finalSeed;
|
||||
|
||||
if(!_useNative ||
|
||||
!_useIso)
|
||||
return BigEndianBitConverter.GetBytes(crc);
|
||||
|
||||
crc32_final(_nativeContext, ref crc);
|
||||
crc32_free(_nativeContext);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(crc);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint crc = _hashInt ^ _finalSeed;
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed).Length; i++)
|
||||
crc32Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed)[i].ToString("x2"));
|
||||
if(_useNative && _useIso)
|
||||
{
|
||||
crc32_final(_nativeContext, ref crc);
|
||||
crc32_free(_nativeContext);
|
||||
}
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++)
|
||||
crc32Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2"));
|
||||
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr crc32_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc32_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc32_final(IntPtr ctx, ref uint crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void crc32_free(IntPtr ctx);
|
||||
|
||||
static uint[][] GenerateTable(uint polynomial)
|
||||
{
|
||||
uint[][] table = new uint[8][];
|
||||
@@ -410,8 +458,16 @@ namespace Aaru.Checksums
|
||||
return table;
|
||||
}
|
||||
|
||||
static void Step(ref uint previousCrc, uint[][] table, byte[] data, uint len, bool useIso)
|
||||
static void Step(ref uint previousCrc, uint[][] table, byte[] data, uint len, bool useIso, bool useNative,
|
||||
IntPtr nativeContext)
|
||||
{
|
||||
if(useNative && useIso)
|
||||
{
|
||||
crc32_update(nativeContext, data, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int currentPos = 0;
|
||||
|
||||
if(useIso)
|
||||
@@ -426,7 +482,7 @@ namespace Aaru.Checksums
|
||||
|
||||
if(blocks > 0)
|
||||
{
|
||||
previousCrc = ~Clmul.Step(data, blocks * 64, ~previousCrc);
|
||||
previousCrc = ~CRC32.Clmul.Step(data, blocks * 64, ~previousCrc);
|
||||
|
||||
currentPos = (int)(blocks * 64);
|
||||
len -= blocks * 64;
|
||||
@@ -505,6 +561,16 @@ namespace Aaru.Checksums
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
bool useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative && useIso)
|
||||
{
|
||||
nativeContext = crc32_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
uint localHashInt = seed;
|
||||
@@ -516,14 +582,20 @@ namespace Aaru.Checksums
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read,
|
||||
polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED);
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read, useIso, useNative, nativeContext);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
if(useNative && useIso)
|
||||
{
|
||||
crc32_final(nativeContext, ref localHashInt);
|
||||
crc32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
@@ -550,14 +622,31 @@ namespace Aaru.Checksums
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed)
|
||||
{
|
||||
bool useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative && useIso)
|
||||
{
|
||||
nativeContext = crc32_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
uint localHashInt = seed;
|
||||
|
||||
uint[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
Step(ref localHashInt, localTable, data, len, polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED);
|
||||
Step(ref localHashInt, localTable, data, len, useIso, useNative, nativeContext);
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
if(useNative && useIso)
|
||||
{
|
||||
crc32_final(nativeContext, ref localHashInt);
|
||||
crc32_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
var crc32Output = new StringBuilder();
|
||||
|
||||
|
||||
115
CRC64Context.cs
115
CRC64Context.cs
@@ -32,9 +32,9 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System.Text;
|
||||
using Aaru.Checksums.CRC64;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
@@ -274,8 +274,10 @@ namespace Aaru.Checksums
|
||||
};
|
||||
|
||||
readonly ulong _finalSeed;
|
||||
readonly IntPtr _nativeContext;
|
||||
readonly ulong[][] _table;
|
||||
readonly bool _useEcma;
|
||||
readonly bool _useNative;
|
||||
ulong _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
||||
@@ -285,22 +287,36 @@ namespace Aaru.Checksums
|
||||
_table = _ecmaCrc64Table;
|
||||
_finalSeed = CRC64_ECMA_SEED;
|
||||
_useEcma = true;
|
||||
|
||||
if(!Native.IsSupported)
|
||||
return;
|
||||
|
||||
_nativeContext = crc64_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
public Crc64Context(ulong polynomial, ulong seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
_table = GenerateTable(polynomial);
|
||||
_finalSeed = seed;
|
||||
_useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||
|
||||
if(Native.IsSupported && _useEcma)
|
||||
{
|
||||
_nativeContext = crc64_init();
|
||||
_useNative = _nativeContext != IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
_table = GenerateTable(polynomial);
|
||||
}
|
||||
|
||||
/// <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 _hashInt, _table, data, len, _useEcma);
|
||||
public void Update(byte[] data, uint len) =>
|
||||
Step(ref _hashInt, _table, data, len, _useEcma, _useNative, _nativeContext);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
@@ -309,20 +325,52 @@ namespace Aaru.Checksums
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed);
|
||||
public byte[] Final()
|
||||
{
|
||||
ulong crc = _hashInt ^ _finalSeed;
|
||||
|
||||
if(!_useNative ||
|
||||
!_useEcma)
|
||||
return BigEndianBitConverter.GetBytes(crc);
|
||||
|
||||
crc64_final(_nativeContext, ref crc);
|
||||
crc64_free(_nativeContext);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(crc);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
ulong crc = _hashInt ^ _finalSeed;
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed).Length; i++)
|
||||
crc64Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed)[i].ToString("x2"));
|
||||
if(_useNative && _useEcma)
|
||||
{
|
||||
crc64_final(_nativeContext, ref crc);
|
||||
crc64_free(_nativeContext);
|
||||
}
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++)
|
||||
crc64Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2"));
|
||||
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern IntPtr crc64_init();
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc64_update(IntPtr ctx, byte[] data, uint len);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern int crc64_final(IntPtr ctx, ref ulong crc);
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern void crc64_free(IntPtr ctx);
|
||||
|
||||
static ulong[][] GenerateTable(ulong polynomial)
|
||||
{
|
||||
ulong[][] table = new ulong[8][];
|
||||
@@ -350,8 +398,16 @@ namespace Aaru.Checksums
|
||||
return table;
|
||||
}
|
||||
|
||||
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma)
|
||||
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma, bool useNative,
|
||||
IntPtr nativeContext)
|
||||
{
|
||||
if(useNative && useEcma)
|
||||
{
|
||||
crc64_update(nativeContext, data, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int dataOff = 0;
|
||||
|
||||
if(useEcma &&
|
||||
@@ -365,7 +421,7 @@ namespace Aaru.Checksums
|
||||
|
||||
if(blocks > 0)
|
||||
{
|
||||
previousCrc = ~Clmul.Step(~previousCrc, data, blocks * 32);
|
||||
previousCrc = ~CRC64.Clmul.Step(~previousCrc, data, blocks * 32);
|
||||
|
||||
dataOff = (int)(blocks * 32);
|
||||
len -= blocks * 32;
|
||||
@@ -424,6 +480,16 @@ namespace Aaru.Checksums
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative && useEcma)
|
||||
{
|
||||
nativeContext = crc64_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
ulong localHashInt = seed;
|
||||
@@ -435,14 +501,20 @@ namespace Aaru.Checksums
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read,
|
||||
polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read, useEcma, useNative, nativeContext);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
if(useNative && useEcma)
|
||||
{
|
||||
crc64_final(nativeContext, ref localHashInt);
|
||||
crc64_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
@@ -469,14 +541,31 @@ namespace Aaru.Checksums
|
||||
/// <param name="seed">CRC seed</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
|
||||
{
|
||||
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||
bool useNative = Native.IsSupported;
|
||||
IntPtr nativeContext = IntPtr.Zero;
|
||||
|
||||
if(useNative && useEcma)
|
||||
{
|
||||
nativeContext = crc64_init();
|
||||
useNative = nativeContext != IntPtr.Zero;
|
||||
}
|
||||
|
||||
ulong localHashInt = seed;
|
||||
|
||||
ulong[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
Step(ref localHashInt, localTable, data, len, polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
||||
Step(ref localHashInt, localTable, data, len, useEcma, useNative, nativeContext);
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
if(useNative && useEcma)
|
||||
{
|
||||
crc64_final(nativeContext, ref localHashInt);
|
||||
crc64_free(nativeContext);
|
||||
}
|
||||
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
var crc64Output = new StringBuilder();
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -42,22 +44,30 @@ namespace Aaru.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;
|
||||
readonly bool _useNative;
|
||||
ushort _sum1, _sum2;
|
||||
|
||||
/// <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>
|
||||
@@ -70,6 +80,12 @@ namespace Aaru.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);
|
||||
}
|
||||
|
||||
@@ -77,8 +93,15 @@ namespace Aaru.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"));
|
||||
@@ -86,8 +109,28 @@ namespace Aaru.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;
|
||||
@@ -251,6 +294,17 @@ namespace Aaru.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;
|
||||
@@ -261,13 +315,19 @@ namespace Aaru.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();
|
||||
@@ -286,13 +346,30 @@ namespace Aaru.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();
|
||||
@@ -315,20 +392,29 @@ namespace Aaru.Checksums
|
||||
{
|
||||
const byte FLETCHER_MODULE = 0xFF;
|
||||
const byte NMAX = 22;
|
||||
byte _sum1, _sum2;
|
||||
|
||||
readonly IntPtr _nativeContext;
|
||||
readonly bool _useNative;
|
||||
byte _sum1, _sum2;
|
||||
|
||||
/// <summary>Initializes the Fletcher-16 sums</summary>
|
||||
public Fletcher16Context()
|
||||
{
|
||||
_sum1 = 0xFF;
|
||||
_sum2 = 0xFF;
|
||||
|
||||
if(!Native.IsSupported)
|
||||
return;
|
||||
|
||||
_nativeContext = fletcher16_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>
|
||||
@@ -341,6 +427,12 @@ namespace Aaru.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 +440,15 @@ namespace Aaru.Checksums
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
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 +456,28 @@ namespace Aaru.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 +621,17 @@ namespace Aaru.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 = fletcher16_init();
|
||||
|
||||
if(nativeContext == IntPtr.Zero)
|
||||
useNative = false;
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
byte localSum1 = 0xFF;
|
||||
@@ -512,13 +642,19 @@ namespace Aaru.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 +673,30 @@ namespace Aaru.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 = 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();
|
||||
|
||||
83
Native.cs
Normal file
83
Native.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Native.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Checksums.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Checks that Aaru.Checksums.Native library is available and usable.
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
{
|
||||
public static class Native
|
||||
{
|
||||
static bool _checked;
|
||||
static bool _supported;
|
||||
|
||||
/// <summary>Set to return native as never supported</summary>
|
||||
public static bool ForceManaged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set to <c>true</c> the native library was found and loaded correctly and its reported version is
|
||||
/// compatible.
|
||||
/// </summary>
|
||||
public static bool IsSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
if(ForceManaged)
|
||||
return false;
|
||||
|
||||
if(_checked)
|
||||
return _supported;
|
||||
|
||||
ulong version;
|
||||
_checked = true;
|
||||
|
||||
try
|
||||
{
|
||||
version = get_acn_version();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_supported = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Check version compatibility
|
||||
_supported = version >= 0x06000000;
|
||||
|
||||
return _supported;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||
static extern ulong get_acn_version();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user